// JavaScript Document
/**
*即将修改的功能：
*	目前步骤的关系比较分散，对步骤的删除，步骤具体某个关系的删除没有做统一的规划
*	因为每个步骤的对象具体配置的表单都是保存起来的，所以需要保存这个表单对象。
*/
define(
    function(require) {
	var zrender = require('zrender');
	var zrEvent = require('zrender/tool/event');
	Math.tween = require('zrender/tool/tween');
	var ie = !+"\v1";
(function(window){
	var _doc = document;//局部化document
	var _body = _doc.body;//局部化body
	var zr = zrender.init($('canvas-content'));
	var oprLineId;//操作层线段的ID
	var outLayerOver = false;//判断外层线段是否触发over
	var changeNameId;
	//该对象用来保存处理用户双击步骤图形修改名字的相关变量
	var stepClick = {
		judge : false,
		lastTime : 0,
		lastTag : ''	
	};
	/*该对象用来保存新建线段时是否需要步骤边框上四个小圆圈的提示功能，以及调整
	*start, 表示用户点击了线段工具
	*adjust, 表示用户在点击了线段工具后，鼠标进入步骤图形范围内四个范围提示小圆圈显示，并且用户将鼠标放到了其中某个小圆圈。在这种情况下判断为可以将该条线段的起点调整到小圆圈的圆心上。 当进入小圆圈触发mouseover时为true,mouseout时为false。
	*pos, 当前小圆圈相对于画布顶点的坐标，用来作为线段的起点。
	*finished, 在起点mouseup后鼠标移动仍会触发步骤的over，该变量在updateDot执行完后调整true。
	*stepId, 小圆圈所对应的步骤
	*direction, 线段和步骤链接点在步骤图形上的位置，即上下左右
	*/
	var lineStartJudge = {
		start : false,
		adjust : false,
		pos : [],
		finished : true,
		stepId : '',
		direction : ''		
	}
	var tempLine;//该对象用来保存即将绘制线段的shapeList关系，具体内容参考shapeList.
	var listId = [];//该变量用来保存 线段起点触发了步骤范围小黄圈后，步骤图形在shapList里面的键值。
	var stepInputDiv = $_class("input-step-name")[0];
	var stepInput = stepInputDiv.getElementsByTagName("input")[0];
	//开始、结束点和步骤号移动时x和y轴方向对齐线是否处于显示状态，即opacity的值。
	var stepLineTip = {
		x : '',
		y : ''	
	}
	var listTag; //步骤移动中，该步骤对应的dancer.shapelist对象。
	var flowProgressSpan = $_class("new-step-sch", "div")[0].getElementsByTagName("span");
	/*局部框选时, 需要修改移动步骤的关联线段。
	*need, 判断为局部框选时为true;
	*listTag, 该线段存在shpeList上面的对象。
	*************************/
	var partChoice = {
		stepNeed : false,
		listTag : [],
		lineNeed : false,
		whichPort : []
	}
	/*画布上图形区域外画框选图形, mousedown开始添加矩形信息，如果直接move的话就修改框框的长和宽, up就直接销毁图形。
	*tag, 矩形对象。
	*id, 默认为choiceRec，比较固定。
	*start, 矩形的开始坐标
	*draw, mousemove是否修改矩形的大小。在down的时候值为true, up就改为false,默认为false.
	************************/
	var choiceRecInfo = {
		tag : '',
		id : 'choiceRec',
		start : [],
		draw : false	
	}
	var clickArr = [];//图形点击对象的集合，可能是一个也可能是多个。
	var moved = false;//监控图形在down后是否move，如果move了就不触发click效果.
	var groupMove = false;//群体移动判断。
	var totalDx = totalDy = 0;//图形移动中，根据ondift的返回值累计当前一共移动了多少个像素。
	var upShape = '';//画布上up的对象，因为image无法在事件代理中触发，故将img对象交给upShape.
	var stepArr = [];//步骤图形的集合。
	//startStepObj记录了每个步骤从该步骤出去的M B N关系;
	//步骤的空间位置,[0]表示其所在的行， [1]表示其在该行的第几个，→方向计算。
	var stepObj = {};
	var brokenPoints = [];//每条折线折点的集合。
	var brokenLevel = 10;//折线的div，每条折线放到不同的canvas里面，提高刷新效率。
	var gongSiName = $("gsName");
	var menuShow  = false;
	var tipWrap = $_class("footer hide", "div")[0];
	var tipFont = $_class("wrong-mes", "span")[0];
	var scrollTop = 0;//canvas包含div的卷去高；
	/*当前模式对象，默认为非受控模式(free)，受控时为control
	*level, 水平方向的距离;
	*vertical, 垂直方向的距离
	*****************************************/
	var modelTarget = {
		"current" : "contorl",
		"level" : 40,
		"vertical" : 40	
	}
	//控制模式下，从"开始"步骤的Y+40开始，每隔40+38(受控间隔+步骤图形的高)个距离就是该数组的键值。
	var solidArr = [];
	
	
/*		var timeArr = ['zero','one','two','three','four','five','six','seven','eight','nine'];
		var timeTag = $("clockSwitch");
		var changeTime = function() {
			timeTag.className = timeArr[i];
			i++;
			if(i == 10) {
				i = 0;	
			}
		}
		setInterval(changeTime, 1000);
		var i = 0*/

	
	goFlow = function() {
		return new goFlow.init();	
	}
	goFlow.init = function() {
			
	}

	/*judge说明，该对象用来阻止图形默认的isCover判断，即不触发其他图形的hover事件.
	*lineDrag, 当需要新画线段时，因为要判断是否进入步骤并建立线与步骤的关系，所以不触发hover.
	*updating, 线的终点未确定时，移动中不触发自身的hover效果。
	*stepDarg, 步骤移动中不触发。
	*choiceMoving, 框选图形移动中不触发over事件。
	****************************/
	goFlow.judge = {
		lineDrag : false,
		updating : false,	
		stepDrag : false,
		choiceMoving : false
	};
	goFlow.prototype = goFlow.init.prototype;
	//监听事件初始化。
	goFlow.init.monitor = function(){
		String.prototype.Trim=function(){
			return this.replace(/(^\s*)|(\s*$)/g, "");
		}

		var tag, url, event, childs, sure = false;
		var flwName;
		var _modelDiv = $_class("model-config-wrap hide", "div")[0];
		var _modelVerticalTag = $("model-vertical");
		var _modelLevelTag = $("model-level");
		var _modelCheck = $_class("open-model-check", "input")[0];
		var _modelStrong = $_class("model-strong", "strong")[0];
		var _truthStrong = $_class("truth-strong", "strong")[0];
		var _modelChoice = $_class("model-choice", "div")[0];
		//实时调整canvas父窗口的大小.
		var flowFather = $("flowFather");
		var canvasContent = $("canvas-content").firstChild;
		var _width = _body.clientWidth - 50
		var _height = _body.clientHeight - 50 + "px";
		var _flwChangeWrap = $_class("flw-change-wrap hide", "div")[0];
		var lastLabelNum = 1;
		var stepSqlTag = '', stepSqlImg = '';
		flowFather.style.cssText = "width:"+_width+"px;height:"+_height;
		canvasContent.style.cssText = "width:"+(_width-20)+"px;height:1500px";
		window.onresize = function() {
			flowFather.style.cssText = "width:"+(_body.clientWidth - 50 )+ "px;height:" +(_body.clientHeight - 50)+ "px";
		}
		flowFather.onscroll = function() {
			scrollTop = this.scrollTop;	
		}
		//屏蔽右键
		_doc.oncontextmenu = function (event){
			event = event || window.event;
			tag = getEventTag(event);
			if("stpDiv" == tag.className) {
				//dba.currStep = tag.innerHTML;
				//dancer.menu(event);	
			}
			return false;
		}
		_doc.onclick = function(event) {
			event = event || window.event;
			var name, steps, curState, x, y, ctx ;
			tag = getEventTag(event);
			switch(tag.className) {
				case "opr-model":
/*						if(!dba.named) {
							alert("请先填写流程信息");	
							return false;
						}*/
						dancer.oprModel[dancer.opreateNum].parentNode.className = "pic-li";
						switch(tag.id) {
							case "choice":
								if(0 != dancer.opreateNum) {
									drawSwitch(dancer.opreateNum);
								}
								dancer.opreateNum = 0;
								tag.parentNode.className = "cur-model-li";
								goFlow.judge.lineDrag = false;
								lineStartJudge.start = false;
								break;	
							case "normalStep":
							case "dynamicStep":
								//个性判断
								if("normalStep" == tag.id ) {
									if(1 != dancer.opreateNum) {
										drawSwitch(dancer.opreateNum);
									}
									dancer.opreateNum = 1;	
								}
								else {
									if(2 != dancer.opreateNum) {
										drawSwitch(dancer.opreateNum);
									}
									dancer.opreateNum = 2;
								}
								tag.parentNode.className = "cur-model-li";
								mousePos = getMousePos(event);
								dancer.stepClick.style.left = mousePos.x - 10 - dancer.canvasWrap[0] + "px";
								dancer.stepClick.style.top = mousePos.y - 10 -  dancer.canvasWrap[1] + "px";
								dancer.stepClick.className = "stepclick show-inline";
								dba.moveTag = dancer.stepClick;
								dba.moveTag.style.cursor = "default";
								moveDefault();
								break;	
							case "nArr":
								if(3 != dancer.opreateNum) {
									drawSwitch(dancer.opreateNum);
								}
								dancer.opreateNum = 3;
								tag.parentNode.className = "cur-model-li";
								lineStartJudge.start = true;
								goFlow.judge.lineDrag = true;
								break;	
							case "mArr":
								if(4 != dancer.opreateNum) {
									drawSwitch(dancer.opreateNum);
								}
								dancer.opreateNum = 4;
								tag.parentNode.className = "cur-model-li";
								lineStartJudge.start = true;
								goFlow.judge.lineDrag = true;
								break;	
							case "bArr":
								if(5 != dancer.opreateNum) {
									drawSwitch(dancer.opreateNum);
								}
								dancer.opreateNum = 5;
								tag.parentNode.className = "cur-model-li";
								lineStartJudge.start = true;
								goFlow.judge.lineDrag = true;
								break;	
							default:
								break;	
						}
					break;
				case "drawPic":
					if(undefined != dancer.lastClick && dancer.lastClick != this) {
						ctx= dancer.lastClick.getContext('2d');
						ctx.strokeStyle = '#608B30';
						ctx.lineWidth = 1;
						ctx.stroke();
					}
					else {
						ctx = this.getContext('2d');
						ctx.strokeStyle = "#608B30";
						ctx.lineWidth = 3;	
						ctx.stroke();
						dancer.lastClick = this;
					}
					break;
				case "flw_up":
					break;
				case "stepchoice_choice":
					if(undefined != dba.whichStep) {
						dba.whichStep.focus();
						dba.whichStep.value = tag.innerHTML.split("__")[0];	
						dba.whichStep.onblur = function() {dba.whichStep.onchange();}
					}
					break;
				case "qx-add-font":
					dba.addQxModel(tag);
					break;
				case "add_line":
					dba.newFlwLine();	
					break;
				case "del_line":
					dancer.delFlwLine();	
					break;
				case "info-move-right show-block":
					if(0 != dba.currentLi) {
						if(!dba.moveCont) {
							dba.moveCont = true;
							dancer.moveInfo("right");
						}
					}
					break;
				case "info-move-left show-block":
					if(2 != dba.currentLi) {
						if(!dba.moveCont) {
							dba.moveCont = true;
							dancer.moveInfo("left");
						}
					}
					break;
				case "info_dir":
					if("dirleft" == tag.id && 0 != dba.currentLi) {
						if(!dba.moveCont) {
							dba.moveCont = true;
							dancer.moveInfo("right");	
						}
					}
					else if("dirright" == tag.id && 2 != dba.currentLi){
						if(!dba.moveCont) {
							dba.moveCont = true;
							dancer.moveInfo("left");	
						}
					}
					break;
				case "save-info":
					dba.saveData();	
					break;
				case "info-close" :
					if("block" == realStyle(dba.saveBut, "display")) {
						sure = confirm("你有数据尚未保存，是否保存数据并退出");	
					}
					if(sure) {
						dba.saveData();	
					}
					dba.infoTag.className = "info-wrap hide";
					if(dba.monitoring.monitor) {
						clearInterval(dba.monitoring.monitor);
					};
					dba.saveBut.style.display = "none";
					if(dba.hasChild) {
						for(var i = 0, cont;cont = dba.contArr[i++];) {
							childs = cont.childNodes;
							for(var j=0,child;child = childs[j++];) {
								cont.removeChild(child);	
							}	
						}	
					}
					break;
				case "pl-but":
					if("取消" == tag.value) {
						dancer.cansoleGh();
					}
					else {
						dba.addQxLine();	
					}
					break;
				case "flw_input flw_sel":
				case "flw_input":
				case "flw_check":
					if('' != dba.flow ) {
						formRespond(tag);
					}
					break;
				case "new_flw_name":
					if("点击命名新流程" == tag.value) {
						tag.select();
					}
					break;
				case "flw_info_switch flw_switch_down":
				case "flw_info_switch flw_switch_up":
					if(undefined == dba.clinfo) {
						dba.clinfo = $("lcinfo");	
					} 
					curState = realStyle(dba.clinfo, "display");
					if("none" == curState) {
						dba.clinfo.style.display = "block";	
						tag.className = "flw_info_switch flw_switch_up";
					}
					else {
						dba.clinfo.style.display = "none";	
						tag.className = "flw_info_switch flw_switch_down";
					}
					break;
				case "model-a a-control":
				case "model-img img-one":
					modelTarget.current = "control";
					modelTarget.level =_modelLevelTag.value;
					modelTarget.vertical =  _modelVerticalTag.value;
					_modelStrong.innerHTML = "C";
					break;
				case "model-a a-uncontrol":
				case "model-img img-two":
					modelTarget.current = "free";
					_modelStrong.innerHTML = "F";
					break;
				case "model-a a-config":
				case "model-img img-three":
					_modelDiv.className = "model-config-wrap";
					break;
				case "step-truth":
				case "step-truth-text":
					if(dancer.showStepRelation) {
						_truthStrong.innerHTML = "C";
						dancer.showStepRelation = false;
					}
					else {
						_truthStrong.innerHTML = "E";
						dancer.showStepRelation = true;
					}
					break;
				case "config-button model-affirm":
					modelTarget.level = _modelLevelTag.value;
					modelTarget.vertical = _modelVerticalTag.value;
					if(_modelCheck.checked) {
						modelTarget.current = "control";	
					}
					else {
						modelTarget.current = "free";		
					}
					_modelDiv.className = "model-config-wrap hide";
					break;
				case "config-button model-cancel":
				case "model-close":
					 _modelDiv.className = "model-config-wrap hide";
					break;
				case "mes-td-selected": 
					if(startTip.moreThanTwenty) {
						startTip.clickToChoice(tag.parentNode.rowIndex - 1);
					}
					else {
						startTip.clickToChoice(tag.parentNode.rowIndex);
					}
					break;
				case "flow-change":
				case "flow-change-text":
					_flwChangeWrap.className = "flw-change-wrap show-block";
					startTip.changePos(); 
					break; 
				case "flw-change-cancel":
					_flwChangeWrap.className = "flw-change-wrap hide"; 
					break;
				case "step-relation-label" :
					tag.nextSibling.className = "ease-show-back";
					_relLablSwitch(tag);
					break;
				case "step-relation-close" : 
					dba.sqlRelationDiv.className = "step-relation hide";
					break;
				case "step-relation-save button":
					dba.sqlRelationDiv.className = "step-relation hide";
					_saveRltSql();
					break;
				case "cloud":
					var cloudTag = tag;
				 	tag.className = "cloud cloud-close";
					var img = tag.firstChild;
					img.setAttribute("src", "images/cloud_ok.png");
					dba.rightConfig = dba.rightConfig || {
						currentShow : 3,
						configDivHeight : [60, 130, 100, 30, 30], 
						rightModel : '',
						rightListUl : '',
						sectionWrapDiv : $_class("config-section-wrap", "div")[0],  
						sectionList : {},
						heightList : {},
						authorityList : {},
						flwConfigList : {},
						labelShowList:{},
						wrapDivList : {},
						stepList : []
						
					};
					dba.rightConfig.authorityConfig =  {
						currSpan : '',
						html : '',
						lis : 0	
					}
					//先组装步骤列表.
					_loadStepList();
					dba.rightConfig.currentWrapDiv = dba.rightConfig.flwWrapDiv;
					$_class("right-config-container", "div")[0].className = "right-config-container open";
					//云移动。
					var top = -20, ulTag = dba.rightConfig.leftUlTag;
					var time = 0, len = dba.stepRlt.length - 3;
					var _moveCloud = function() {
						var liTag;
						top = top + 50;
						cloudTag.style.top = top + "px";
						if(0 == time) {
							liTag = ulTag.childNodes[0];
							setTimeout(function() {liTag.className = "currentLi"}, 200);	
						}
						else {
							liTag = ulTag.childNodes[time];
							setTimeout(function() {liTag.className = ""}, 200);	
						}
						time++;
						if(len == time) {
							clearInterval(startCloudMove);	
						}
					}
					var startCloudMove = setInterval(_moveCloud, 500);
					break;
				case "cloud cloud-close":
					var timeArr = ['zero','one','two','three','four','five','six','seven','eight','nine'];
					$("overlay").className = "overlay-div overlay-show";
					var sections = dba.rightConfig.sectionWrapDiv.getElementsByTagName("section");
					var len  = sections.length;
					var decadeNum = parseInt(len/10);
					var unitNum = Number(len) - decadeNum * 10;
					$("decade").className = timeArr[decadeNum] +　" timeWrap";
					$("unit").className = timeArr[unitNum] + " timeWrap";
					$("clock").className = "save-data-process process-show";
					setTimeout(_saveData, 1000);
					break;
				case "config-qx-add":
					//如果现在有打开的权限标签就先关闭。
					if('' !=  dba.rightConfig.authorityConfig.currSpan) {
						dba.rightConfig.authorityConfig.divTag.style.height = "0px";
						dba.rightConfig.authorityConfig.aTag.className = "config-right-a";
						dba.rightConfig.configDivHeight[4] = dba.rightConfig.authorityConfig.lis*17 + 35;
						dba.rightConfig.rightWrapDiv.style.height = dba.rightConfig.configDivHeight[4] + "px";
					}
					tag.className = "config-qx-add hide";
					getPrevioussibling(tag).className = "config-right-button";
					parent = tag.parentNode;
					dba.rightConfig.rightModel.innerHTML = dba.html.rightConfig.rightModel;
					dba.rightConfig.rightListUl.className = "config-right-list overlay-contentscale"
					dba.rightConfig.rightModel.className = "config-right-model";
					dba.rightConfig.configDivHeight[4] = 320;
					parent.style.height = "320px";
					dba.rightConfig.qxWrapDiv = parent;
					break;
				case "right-config-back":
					tag.parentNode.className = "right-config-container close";
				case "label-h1":
					_changeLableHight(tag.parentNode);
					break;
				case "config-flw-span":
					_configFlwSpanClick(tag);
					break;
				case "config-right-span":
					if('' !=  dba.rightConfig.authorityConfig.currSpan) {
						dba.rightConfig.authorityConfig.divTag.style.height = "0px";
						dba.rightConfig.authorityConfig.aTag.className = "config-right-a";
						if(dba.rightConfig.authorityConfig.currSpan == tag) { //如果是同一个就关闭。
							dba.rightConfig.authorityConfig.aTag.className = "config-right-a";
							dba.rightConfig.authorityConfig.divTag.style.height = "0px";
							dba.rightConfig.authorityConfig.currSpan = '';
							dba.rightConfig.configDivHeight[4] = dba.rightConfig.authorityConfig.lis*17 + 40;
							dba.rightConfig.rightWrapDiv.style.height = dba.rightConfig.configDivHeight[4] + "px";
							break;	
						}
					}
					dba.rightConfig.authorityConfig.currSpan = tag;
					dba.rightConfig.authorityConfig.aTag = tag.parentNode;
					dba.rightConfig.authorityConfig.aTag.className = "config-right-a rotate";
					dba.rightConfig.authorityConfig.currLi = dba.rightConfig.authorityConfig.aTag.praentNode;
					dba.rightConfig.authorityConfig.divTag = getNextSibling(dba.rightConfig.authorityConfig.aTag);
					
					dba.rightConfig.configDivHeight[4] = 250 + dba.rightConfig.authorityConfig.lis*17 + 40;
					dba.rightConfig.rightWrapDiv.style.height = dba.rightConfig.configDivHeight[4] + "px";
					dba.rightConfig.authorityConfig.divTag.style.height = "250px";
					break;
				case "config-flw-a rotate":
					tag.className = "config-flw-a";
					dba.flwRelConfig.divTag.style.height = "0px";
					dba.flwRelConfig.currLi = '';
					dba.flwRelConfig.flwWrapDiv.style.height = dba.rightConfig.lis*17 + 40 + "px";
					dba.rightConfig.configDivHeight[3] = dba.rightConfig.lis*17 + 40;
					break;
				case "right-opr right-add": //右侧权限添加按钮。
					dba.rightConfig.configDivHeight[4] = dba.rightConfig.configDivHeight[4] + 30; 
					dba.rightConfig.qxWrapDiv.style.height = dba.rightConfig.configDivHeight[4] + "px";
					
					li = ce('li');
					li.innerHTML = '<label></label><input class="right-model-form" data-form="4" type="text" style="width:72px;" value="" name="quan_GUPNUM"><em class="right-opr right-del"></em>';
					parentNode = tag.parentNode.parentNode;
					parentNode.insertBefore(li, parentNode.lastChild);

					break;
				case "right-opr right-del": //右侧权限删除行
					tag.parentNode.parentNode.removeChild(tag.parentNode);
					dba.rightConfig.configDivHeight[4] = dba.rightConfig.configDivHeight[4] - 30; 
					dba.rightConfig.qxWrapDiv.style.height = dba.rightConfig.configDivHeight[4] + "px";
					break;
				case "config-qx-save": //右侧权限保存按钮
					_rightSaveDel(tag);
					break;
				case "config-qx-cancel":
					dba.rightConfig.rightModel.className = "config-right-model ul-scale-0";
					dba.rightConfig.configRightButton.className = "config-right-button hide";
					dba.rightConfig.addRightButton.classNmae = "config-qx-add";
					if('' == dba.rightConfig.rightListUl) {
						dba.rightConfig.configDivHeight[4] = 30;	
						dba.rightConfig.qxWrapDiv.style.height = "30px";
					}
					else {
						dba.rightConfig.configDivHeight[4] = dba.rightConfig.configDivHeight[4] + 30; 
						dba.rightConfig.qxWrapDiv.style.height = dba.rightConfig.configDivHeight[4] + "px";
						dba.rightConfig.rightListUl.className = "config-right-list overlay-contentscale overlay-open";
					}
					break;
				case "config-del-right"://删除右侧配置某个已添加权限。	
					rightNum = dba.rightConfig.authorityConfig.currSpan.innerHTML.split(":")[1].Trim();
					delete dba.stepRight[dba.rightConfig.curConfigStep][rightNum];
					dba.rightConfig.authorityConfig.lis = dba.rightConfig.authorityConfig.lis - 1; 
					dba.rightConfig.rightListUl.removeChild(dba.rightConfig.authorityConfig.aTag.parentNode);
					dba.rightConfig.configDivHeight[4] = dba.rightConfig.authorityConfig.lis*17 + 40;
					dba.rightConfig.rightWrapDiv.style.height = dba.rightConfig.configDivHeight[4] + "px";
					break;
				case "stepNum-list-a"://右侧stepNum-list切换
					_stepNumListSwtich(tag);
					break;
				case "config-flw-save":	 //	  添加保存操作
					
				case "config-flw-del":  //   添加删除操作
				case "config-flw-veto":		//	  添加否决操作。
					break;
				default:
					break;	
			}
			/**
			*	步骤流转关系配置时，多个步骤SQL填写textarea切换方法
			*	@param {obj} tag 当前点击的label对象。
			*	说明：1，这里使用requestAnimationFrame来优化div移动效果
			*		  2，tween计算缓动的实时变化值O(∩_∩)O~
			*/
			function _relLablSwitch(tag) {
				var nextDiv = tag.nextSibling;
				var lastDiv = $("item_"+lastLabelNum).nextSibling;
				var currentLabelNum = tag.id.split("_")[1];
				if(currentLabelNum == lastLabelNum) {
					return false;	
				}	
				var start = 0, during = 20;
				_run = function() {
						start++;
						var height = Math.tween.Quint.easeOut(start, 0, 90, during);
						lastDiv.style.height = (90 - height) + "px";
						nextDiv.style.height = height+ "px";
						if (start < during) {
							 requestAnimationFrame(_run);	
						}
						else {
							lastDiv.className = "hide";
							nextDiv.className = "show-block";
							lastLabelNum = currentLabelNum;	
						}
				}
				_run();
			}
			/**
			* 保存textarea里面的sql条件。。
			*/
			function _saveRltSql() {
				var areas = $_class("relation-sql", "textarea");
				var stepDelTag = dba.stepDel[dba.currStep], id;
				for(var i = 0, len = areas.length; i < len; i++) {
					id = areas[i].id.split("_")[1];
					stepDelTag[id][9] = areas[i].value;
				}
				dba.currStep = '';
			}
			/**
			* 根据 solidArr 对右侧配置列表 stepnum做赋值。
			*/
			function _loadStepList(){
				var curArr, innerHtml = '';
				var _solidArr = solidArr;
				var _len = _solidArr.length - 1;
				var stepRlt = dba.stepRlt;
				var flwName;
				var ul = ce("ul");
				for(var i = 0; i <_len; i++) {
					curArr = _solidArr[i];	
					for(var j = 0, curLen = curArr.length; j < curLen; j++) {
						//innerHtml = innerHtml + '<li><a><span>'+stepRlt[curArr[j]].stepNum+'</span><span>'+stepRlt[curArr[j]].stepName+'</span></a><div class="config-icon"><img src="images/config2.png" /></div></li>';	
						innerHtml = innerHtml + '<li class="hide"><a class="stepNum-list-a">'+stepRlt[curArr[j]].stepNum+'</a><div class="config-icon"><img src="images/config2.png" /></div></li>';	
						dba.rightConfig.stepList.push(stepRlt[curArr[j]].stepNum);
					}
				}
				ul.innerHTML = innerHtml;
				dba.rightConfig.curConfigStep = stepRlt[_solidArr[0]].stepNum;
				dba.rightConfig.currentListLi = ul.firstChild; 
				//dba.rightConfig.currentListLi.className = "currentLi";
				$_class("stepNum-list", "div")[0].appendChild(ul);
				dba.rightConfig.leftUlTag = ul;
				var section  = ce("section");
				section.className = "config-section";
				section.innerHTML = dba.html.rightConfig.sectionContent;
				_resetRightConfig(section);

				dba.rightConfig.sectionWrapDiv.appendChild(section);
				dba.rightConfig.configSection = section;
				dba.rightConfig.sectionList[dba.rightConfig.curConfigStep] = section; 
				_createFlowRel(solidArr[0][0], dba.stepRlt[solidArr[0][0]].rltArr);
			}
			/**
			*  根据stepRlt生成流转配置信息。
			*/
			function _createFlowRel(num, rlt) {
				_len = rlt.length;
				ul = ce("ul");
				innerHtml = '';
				dba.rightConfig.rlt = {};
				dba.rightConfig.rlt[num] = [];
				for(var i = 0, j=0; i < _len; i++) {
					if("start" == rlt[i].type) {
						switch(rlt[i].flwType) {
							case 3:
							case "N":
								flwName = '流转';
								break;
							case 4:
							case "M":
								flwName = "返回";
							case 5:
							case "B":
								flwName = "退签";
								break;
									
						}
						j++;
						innerHtml = innerHtml + '<li><a class="config-flw-a"><i></i><span class="config-flw-span">'+flwName + ' : '+dba.stepRlt[rlt[i].tagId[1]].stepName+'</span></a>'+dba.html.rightConfig.flwInput+'</li>';	
					//	dba.rightConfig.rlt[num].push(rlt[i].stepNum[1]);	
					}	
				}
				ul.innerHTML = innerHtml;

				dba.rightConfig.flwWrapDiv.style.height = j*17 + 40 + "px";
				dba.rightConfig.flwWrapDiv.appendChild(ul);
				//这个时候再定义 配置列表各个div的高度。
				dba.rightConfig.configDivHeight[3] = j * 17 + 40;
				dba.rightConfig.flwConfig =  {
					currSpan : '',
					currentShow : 3,
					tag : tag,
					lis : j //当前有多少个li
				} 
				setTimeout(function(){_configFlwSpanClick(ul.getElementsByTagName("span")[0])}, 400);
			}
			/**
			*右侧配置：流转配置span点击相应事件。
			*@param {obj} tag 当前点击span
			*两种调用：1，用户点击
			*		   2，第一次打开右侧配置，第一个步骤配置默认打开第一个流转配置。
			*/
			function _configFlwSpanClick(tag) {
				if('' !=  dba.rightConfig.flwConfig.currSpan) {
					dba.rightConfig.flwConfig.divTag.style.height = "0px";
					dba.rightConfig.flwConfig.aTag.className = "config-flw-a";
					if(dba.rightConfig.flwConfig.currSpan == tag) { //如果是同一个就关闭。
						dba.rightConfig.flwConfig.aTag.className = "config-flw-a";
						dba.rightConfig.flwConfig.divTag.style.height = "0px";
						dba.rightConfig.flwConfig.currSpan = '';
						dba.rightConfig.configDivHeight[3] = dba.rightConfig.flwConfig.lis*17 + 50;
						dba.rightConfig.flwWrapDiv.style.height = dba.rightConfig.configDivHeight[3] + "px";
						return;
					}
				}
				dba.rightConfig.flwConfig.currSpan = tag;
				dba.rightConfig.flwConfig.aTag = tag.parentNode;
				dba.rightConfig.flwConfig.aTag.className = "config-flw-a rotate";
				dba.rightConfig.flwConfig.currLi = dba.rightConfig.flwConfig.aTag.praentNode;
				dba.rightConfig.flwConfig.divTag = getNextSibling(dba.rightConfig.flwConfig.aTag);

				dba.rightConfig.configDivHeight[3] = 230 + dba.rightConfig.flwConfig.lis*17 + 50;
				dba.rightConfig.flwWrapDiv.style.height = dba.rightConfig.configDivHeight[3] + "px";
				dba.rightConfig.flwConfig.divTag.style.height = "230px";	
			}
			/** 右侧配置 h1点击后切换当前显示的配置大类，修改其下面的div高度
			*@param {object} tag 当前点击的h1
			*/
			function _changeLableHight(tag) {
				var nextSibling = getNextSibling(tag);
				var currentNum = tag.getAttribute("for").split("-")[1];
				if(currentNum == dba.rightConfig.currentShow) {
					return;	
				}
				dba.rightConfig.currentWrapDiv.style.height = "0px"; 
				nextSibling.style.height = dba.rightConfig.configDivHeight[currentNum] + "px";
				dba.rightConfig.currentShow = currentNum;
				dba.rightConfig.currentWrapDiv = nextSibling;
			}
			/**
			* 步骤权限添加确认按钮点击后当前步骤添加权限
			*/
			function _rightSaveDel(tag) {
				var tags = dba.rightConfig.rightModel.getElementsByTagName("*");
				var len = tags.length, formDatas = [];
				var formDatas = $_class("right-model-form","*", dba.rightConfig.rightModel);
				if('' == formDatas[3].value || '' == formDatas[4].value) {
					return false;	
				}
				dba.stepRight = dba.stepRight || {};
				dba.stepRight[dba.rightConfig.curConfigStep] = dba.stepRight[dba.rightConfig.curConfigStep] || {};
				
				var tempRight = {}, 
					rightListUl, 
					innerHtml = dba.html.rightConfig.rightDel,
					len = formDatas.length,
					_len = len - 5;
					
				var fragment = ceDfg();
				tempData = [formDatas[0].value, formDatas[1].value,formDatas[2].value, formDatas[3].value, formDatas[len - 1].value];
				for(i = 0; i < _len; i++) {
					s = formDatas[4 + i].value;
					dba.stepRight[dba.rightConfig.curConfigStep][s] = {
						0 :	tempData[0],
						1 : tempData[1],
						2 : tempData[2],
						3 : tempData[3],
						4 : s,
						5 : tempData[4]
					}
					li = ce("li");
					li.innerHTML = '<a class="config-right-a"><i></i><span class="config-right-span">'+tempData[3]+' : '+ s +'</span></a>';
					div = ce("div");
					div.className = "config-right-wrap"
					div.innerHTML = innerHtml;
					valTag = dba.getEleForRight(div.getElementsByTagName("*"));
					dba.setData(valTag, tempData);
					li.appendChild(div);
					fragment.appendChild(li);
				}	
				dba.rightConfig.rightListUl.appendChild(fragment);
				
				dba.rightConfig.authorityConfig.html = dba.rightConfig.authorityConfig.html + innerHtml;
				dba.rightConfig.authorityConfig.lis = dba.rightConfig.authorityConfig.lis + _len;
				
				dba.rightConfig.configDivHeight[4] = dba.rightConfig.authorityConfig.lis * 17 + 35;
				dba.rightConfig.qxWrapDiv.style.height = dba.rightConfig.configDivHeight[4] + "px";

				dba.rightConfig.configRightButton.className = "config-right-button hide";	
				dba.rightConfig.rightModel.className = "config-right-model ul-scale-0";
				
				setTimeout(function(){dba.rightConfig.rightListUl.className = "config-right-list overlay-contentscale overlay-open";}, 100);
				dba.rightConfig.addRightButton.className = "config-qx-add";
			}
			/** 右侧配置的左侧步骤列表点击切换步骤配置处理函数
			*@param {obj} tag 点击的要切换的步骤号
			*思路：先将当前步骤的配置写到list里面，再把其隐藏；
			*	   然后判断新切换出来的步骤是否已经配置过，如果配置过直接把section显示出来，否则就新增加。
			*/
			function _stepNumListSwtich(tag){
				var rightConfig = dba.rightConfig;
				rightConfig.currentListLi.className = "";//1， 调整currentLi
				rightConfig.currentListLi = tag.parentNode;
				rightConfig.currentListLi.className = "currentLi";
				var step= rightConfig.curConfigStep;
				rightConfig.heightList[step] = rightConfig.configDivHeight; //2,保存当前每个div的高度
				rightConfig.authorityList[step] = rightConfig.authorityConfig;
				rightConfig.flwConfigList[step] = rightConfig.flwConfig;
				rightConfig.labelShowList[step] = rightConfig.currentShow;
				rightConfig.wrapDivList[step] = rightConfig.currentWrapDiv;

				rightConfig.configSection.className = "config-section config-section-close";  //3，隐藏当前的section
				
				var name = tag.innerHTML; //获取要切换的步骤num
				if(undefined  == rightConfig.sectionList[name]) { //4,显示新的section
					var section = ce("section");	 //4.1 新的配置步骤直接创建
					section.className = "config-section config-section-close";
					rightConfig.sectionWrapDiv.appendChild(section);
					section.innerHTML = dba.html.rightConfig.sectionContent;
					rightConfig.sectionList[name] = section;
					rightConfig.authorityConfig =  {
						currSpan : '',
						html : '',
						lis : 0	
					}
					rightConfig.flwConfig = {
						lis:''	
					};
					rightConfig.currentShow = 3;
				}
				else {
					section = rightConfig.sectionList[name];  //4.2 取出已有的section对象。
					rightConfig.authorityConfig = rightConfig.authorityList[name];
					rightConfig.flwConfig = rightConfig.flwConfigList[name];
					rightConfig.currentShow = rightConfig.labelShowList[name];
					rightConfig.currentWrapDiv = rightConfig.wrapDivList[name];
				}
				rightConfig.curConfigStep = name;
				rightConfig.configSection = section;
				_resetRightConfig(section);//重定向变量，将rightConfig下面的对象重新指向当前section里面的元素。
				rightConfig.configDivHeight = rightConfig.heightList[name] || [60, 130, 100, 0, 30];
				if('' == rightConfig.flwConfig.lis) {
					_createFlowRel(parseInt(name)+2, dba.stepRlt[parseInt(name)+2].rltArr); //生成新的步骤流转关系。
					rightConfig.currentWrapDiv = rightConfig.flwWrapDiv;
				}
				
				setTimeout(function(){section.className = "config-section"}, 200);	
			}
			/**
			* 黑云 点击后的保存函数。
			*/
			function _saveData(){
				var curSection;
					var timeArr = ['zero','one','two','three','four','five','six','seven','eight','nine'];
					$("overlay").className = "overlay-div overlay-show";
					var sections = dba.rightConfig.sectionWrapDiv.getElementsByTagName("section");
					var len  = sections.length;

				var processUnit = $("processunit");
				var processDecade = $("processdecade");
				var stepList = dba.rightConfig.stepList;
				var step = dba.step;
				for(var i = 0; i < len; i++) {
					curSection = sections[i];
					formWrap = $_class("config-div-wrap", "div", curSection); //获取每一个包含div
					stepNum = stepList[i];
					step[stepNum] = {};
					/*for(var j = 0, wraps = formWrap.length; j < wraps; j++) {
						switch(j) {
							case 0:
							case 1:
							case 2:
								formTags = formWrap[j].getElementsByTagName("*");
								for(var k = 0, formLen = formTags.length; k < formLen; k++) {
									form = formTags[k];
									if(inArray(["INPUT", "SELECT", "TEXTAREA"], form.nodeName)) {
										id = form.getAttribute("data");
										if("checkbox" == form.getAttribute("type")) {
											if(form.checked) {
												step[stepNum][id] = 1;	
											} 	
											else {
												step[stepNum][id] = 0;	
											}
											continue;
										}
										step[stepNum][id] = form.value;
									}	
								}	
								break;
							case 3:
								rlts = $_class("config-flw-wrap", "div", formWrap[3]);
								stepDel = dba.stepDel;
								stepDel[stepNum] = [];
								for(k = 0, rltLen =rlts.length; k < rltLen; k++){
									formTags = rlts[k].getElementsByTagName("*");
									tempObj = {};
									for(var h = 0, formLen = formTags.length; h < formLen; h++) {
										form = formTags[k];
										if(inArray(["INPUT", "SELECT", "TEXTAREA"], form.nodeName)) {
											id = form.getAttribute("data");
											if("checkbox" == form.getAttribute("type")) {
												if(form.checked) {
													tempObj[id] = 1;	
												} 	
												else {
													tempObj[id] = 0;	
												}
												continue;
											}
											tempObj[id] = form.value;
											tempObj[6] = dba.rightConfig.rlt[num][h];
										}	
									}
									stepDel[stepNum].push(tempObj);	
								}
								break;
							case 4:
								rights = $_class("config-right-wrap","div", formWrap[4]);
								currentRight = dba.stepRight[stepNum];
								for(var k = 0, rightLen = currentRight.length; k < rightLen; k++) {
									formTags = rights[k].getElementsByTagName("*");
									for(var h = 0, formLen = formTags.length; h < formLen; h++) {
										form = formTags[k];
										if(inArray(["INPUT", "SELECT", "TEXTAREA"], form.nodeName)) {
											id = form.getAttribute("data-form");
											if("checkbox" == form.getAttribute("type")) {
												if(form.checked) {
													currentRight[k][id] = 1;	
												} 	
												else {
													currentRight[k][id] = 0;	
												}
												continue;
											}
											currentRight[k][id] = form.value;
										}	
									}
								}
								break;
						}
					}	*/
					processUnit.className = timeArr[i+1] +　" timeWrap";	
					setTimeout(changeProcess, 500);
				}
				var changeProcess = function() {
					processUnit.className = timeArr[i] +　" timeWrap";	
				}
			}
			/**
			* StepNum list切换时 dba.rightConfig里面的变量需要重置
			* @param {object} tag 当前section。
			*/
			function _resetRightConfig(tag) {
				var eles = tag.getElementsByTagName("*");
				var tagNode = dba.rightConfig;
				for(var i = 0, len = eles.length; i < len ; i++) {
					ele = eles[i];
					if(undefined != ele.className) {
						switch(ele.className) {
							case "config-div-wrap config-relation-div":
								tagNode.flwWrapDiv = ele;
								break;	
							case "config-qx-add" :
								tagNode.addRightButton  = ele;
								break;
							case "config-right-button hide":
								tagNode.configRightButton = ele;
								break;
							case "config-right-model":
								tagNode.rightModel = ele;
								break
							case "config-div config-permissions":
								tagNode.rightParent = ele;
								break;	
							case "config-right-list overlay-contentscale":
								tagNode.rightListUl = ele;
								break;
							case "config-div-wrap config-permissions-div":
								tagNode.rightWrapDiv = ele;
								break;
						}	
					}
				}
			}
		}
		_body.onmousedown = function(event) {
			event = event || window.event;
			tag = getEventTag(event);
			switch(tag.className) {
				case "info-Move":
					dba.moveTag = dba.dataContent;
					dba.moveTag.style.cursor = "move";
					moveDefault();
					break;
				case "pl-font":		
					dba.moveTag = dba.plModel;
					dba.moveTag.style.cursor = "move";
					moveDefault();
					break;
				case "test":
					dba.moveTag = tag;
					moveDefault();
					break;
				case "step-relation-title" :
					dba.moveTag = tag.parentNode;
					moveDefault();
				default:
					break;	
			}
		}
		//input获取焦点事件绑定，避免和快捷键冲突。
        if(document.addEventListener){
                document.addEventListener("focus", _focus_handler, true); //最后一项参数设置为true
                document.addEventListener("blur", _blur_handler, true); //最后一项参数设置为true
        }
        else{
                document.attachEvent("onfocusin", _focus_handler); //注意事件是onfocusin
                document.attachEvent("onfocusout", _blur_handler); //注意事件是onfocusout
        }
		function _focus_handler(event) {
			tag = getEventTag(event);
			if("INPUT" == tag.nodeName || "TEXTAREA" == tag.nodeName) {
				dba.focusTag = tag;
			}
		}
		function _blur_handler(event){
			tag = getEventTag(event);
			if(tag.parentNode == stepInputDiv) {
				var value = tag.value;
				zr.modShape(clickArr[0].id,{
					style : {
						text:value	
					}	
				});		
				dba.step[dba.stepRlt[clickArr[0].id].stepNum][3] = value;
				dba.step[dba.stepRlt[clickArr[0].id].stepNum][4] = value;	
				stepInputDiv.style.left = "-200px";
				zr.refresh();
				dba.stepRlt[clickArr[0].id].stepName = tag.value
				$("gsName").parentNode.focus();
			}
			dba.focusTag = '';
/*			if("step-opcon-area" == tag.className) {
				tag.parentNode.className = "relation-sql-wrap hide";	
				stepSqlImg.setAttribute("src", "images/add_sql.png");
				stepSqlTag.className = "relation-sql-wrap hide";
				stepSqlImg = '';
				stepSqlTag = '';
			}*/
		}
		_body.onmousemove = function(event) {
			event = event || window.event;
			var mousePos, tempLeft, tempRight, addX, addY;
			var sPointX, sPointY, ePointX, ePointY;
			dba.mousePos = getMousePos(event);
			mousePos = [dba.mousePos.x, dba.mousePos.y];
			if(dba.canMove) {
				//dba.moveTag.style.cssText = "left:"+(mousePos[0] - dba.moveTag.startLeft)+"px;top:" + 
					//									(mousePos[1] - dba.moveTag.startTop + scrollTop) + "px";									
				dba.moveTag.style.left = mousePos[0] - dba.moveTag.startLeft+"px";
				dba.moveTag.style.top = mousePos[1] - dba.moveTag.startTop + scrollTop + "px";
			}
			//操作类型确定为线段，鼠标移动尚未确定开始点，判断是否有步骤重合。
			if(lineStartJudge.start && lineStartJudge.finished) {
				lineMovingOver(mousePos[0], mousePos[1]);	
			}
			if(dancer.dotMove) {
				dancer.updateDot(dba.mousePos);
				//这个地方线段开始点确定后，结束点仍在移动中。
				lineMovingOver(mousePos[0], mousePos[1]);	
			}	
			//线段开始点和结束点移动中判断是否进入步骤范围。
			if(dancer.linePortMoving) {
				lineMovingOver(mousePos[0], mousePos[1]);	
			}
		}
		_body.onmouseup = function(event) {
			var tempPos, tempRlt, x, y, id;
			event = event || window.event;
			var tag = getEventTag(event);
			var points, invisible, stepInfo, num, tempStepDel;
			if("sql-img" == tag.className){
				if('' != stepSqlTag) {
					stepSqlImg.setAttribute("src", "images/add_sql.png");
					stepSqlTag.className = "relation-sql-wrap hide";
					if(tag == stepSqlImg) {
						stepSqlImg = '';
						stepSqlTag = '';
						return;
					}
				}
				stepSqlTag = getPrevioussibling(tag);
				stepSqlImg = tag;
				stepSqlImg.setAttribute("src", "images/add_sql_blue.png");
				stepSqlTag.className = "relation-sql-wrap";
				return;
			}
			if('' != stepSqlImg && "step-opcon-area" != tag.className) {
				stepSqlImg.setAttribute("src", "images/add_sql.png");
				stepSqlTag.className = "relation-sql-wrap hide";	
				stepSqlImg = '';
				stepSqlTag = '';
			}
			//setpDateTag, stepDateImg, stepSqlTag, stepSqlImg;
			//chrome下面右键无法触发click事件，这里暂且将其放倒up里面 
			if(tag.className ==  "menu-li") { 
					dba.menuTag.className = "menu-div hide";
					//用于已打开配置页面但是又再次直接打开新的步骤时删除已有子节点
					if(dba.hasChild) {
						for(var i = 0, cont;cont = dba.contArr[i++];) {
							childs = cont.childNodes;
							for(var j=0,child;child = childs[j++];) {
								cont.removeChild(child);	
							}	
						}	
					}
					stepName = dba.stepRlt[dba.currStep].stepName;
					stepInfo = "当前步骤：" + stepName;
					switch(tag.id) {
						case "qx":
							dba.infoMove.innerHTML = stepInfo; 
							dba.hasChild = true;
							dba.infoTag.style.height = "392px";
							dba.qxMsData();
							break;
						case "yw":
							dba.infoMove.innerHTML = stepInfo;
							dba.infoTag.style.height = "315px";
							dba.hasChild = true;
							dba.busData();
							break;	
						case "lc":
							dba.infoMove.innerHTML = stepInfo;
							dba.hasChild = true;
							dba.flwData();
							break;	
						case "add":
							break;
						case "check":
							break;
						default:
							break;
					}
			}
			if("open" == menuShow) {
					x = zrEvent.getX(event);
					y = zrEvent.getY(event);
					dba.menuTag.style.cssText = "left:"+(x + 40 - dancer.canvasWrap[0]) +"px;top:" + (y + 40 - dancer.canvasWrap[1]) + "px";
					dba.menuTag.className = "menu-div show-block";
					menuShow = "close";
			}
			else if("close" == menuShow){
				dba.menuTag.className = "menu-div hide";	
				menuShow = false;
			}
			
			if(dba.canMove && "pic-li" != tag.parentNode.className) {
				if(0 <= tag.className.indexOf("stepclick")) {
					mousePos = getMousePos(event);
					mousePos.x = mousePos.x - dancer.canvasWrap[0];
					mousePos.y = mousePos.y - dancer.canvasWrap[1];
					if("free" == modelTarget.current) {
						id = zr.newShapeId();
						dancer.drawStep(mousePos.x, mousePos.y, dancer.opreateNum, id);
					}
					else {
						id = zr.newShapeId();
						controlModelPos(mousePos.x, mousePos.y, dancer.opreateNum, id);	
						upRltLine(dba.stepIds);
						zr.refresh();
					}
					tempDel = deepClone(dba.defaultStepInfo);
					//修改该步骤的默认流程配置, 初始化。
					tempDel[0] = dba.stepContinue-1;
					tempDel[3] = '步骤_' + tempDel[0];
					tempDel[4] = '步骤_' + tempDel[0];
					tempDel[8] = dancer.opreateNum - 1;	
					//添加步骤ID
					dancer.drawStepNum(id, stepArr[id], dba.stepContinue-1)
					dba.step[dba.stepRlt[id].stepNum] = tempDel;
					dancer.oprModel[dancer.opreateNum].parentNode.className = "pic-li";
					dancer.oprModel[0].parentNode.className = "pic-li cur-model-li";	
					dancer.opreateNum = 0;
				}
				dba.canMove = false;
				dba.moveTag.style.cursor = "";	
				dba.moveTag = '';
			}
			if(dancer.line.start) {
				dancer.line.start = false;	
			}
			///对于画线1和2， 如果lineStartJudge.adjust为false说明点击点不在小圆圈上。反馈给用户错误信息，并删除cloneLine.
			//1, 画线起点
			if((3 <= dancer.opreateNum && dancer.opreateNum <= 5 )&& !dancer.dotMove && "pic-li" != tag.parentNode.className) {
				if(lineStartJudge.adjust) { 
					tempPos = getMousePos(event);
					tempPos.x = parseInt(tempPos.x  - dancer.canvasWrap[0]);
					tempPos.y = parseInt(tempPos.y - dancer.canvasWrap[1]) + scrollTop;
					dancer.dotInit = [tempPos.x, tempPos.y];
					tempLine = {
						"type" : "",
						"x2" : "",
						"y2" : "",
						"id" : dancer.shapList.length + 1,
						"startStep" : '',
						"endStep" : ''
					}

					dancer.dotInit = [lineStartJudge.pos[0], lineStartJudge.pos[1]];
					tempLine.startStep = lineStartJudge.stepId;
					listId[0] = lineStartJudge.stepId;
					tempLine.tempRlt = {
						"type" : "start",
						"lineTag" : "",
						"startPoint" : lineStartJudge.direction,
						"pos" :lineStartJudge.pos	
					}
					tempLine.startDir = lineStartJudge.direction;			
					tempLine.x1 = dancer.dotInit[0] + dancer.canvasWrap[0];
					tempLine.y1 = dancer.dotInit[1] + dancer.canvasWrap[1];
					dancer.shapTag.tag = dancer.drawDotLine(dancer.dotInit, [tempPos.x, tempPos.y]);
					dancer.dotMove = true;
				}				
				else {
					//错误提示
					tipFont.innerHTML = "错误操作!设置连线的起点时，鼠标应放到小红圈上再点击即可。";
					tipWrap.className = "footer show-block";
				}
				return;
			}
			//2, 画线终点。
			if((3 <= dancer.opreateNum && dancer.opreateNum <= 5 ) && dancer.dotMove && "pic-li" != tag.parentNode.className) {
				if(lineStartJudge.adjust) {
					/*画线相关操作判断修改*/
					dancer.oprModel[dancer.opreateNum].parentNode.className = "pic-li";
					dancer.oprModel[0].parentNode.className = "pic-li cur-model-li";
					dancer.dotMove = false;
					goFlow.judge.updating = false;
					lineStartJudge.finished = true;
					lineStartJudge.start = false;
					lineStartJudge.adjust = false;
					//设定结束点
					/*线段属性设定*/
					tag = dancer.shapTag.tag;	
					x = lineStartJudge.pos[0];
					y = lineStartJudge.pos[1];
					tag.style.xEnd = x - tag.position[0];
					tag.style.yEnd = y - tag.position[1];
					tag.style.endX = x;
					tag.style.endY = y;
					//
					x += dancer.canvasWrap[0];
					y += dancer.canvasWrap[1];
					listId[1] = lineStartJudge.stepId
					tempLine.endStep = lineStartJudge.stepId;
					tempLine.endDir = lineStartJudge.direction;
					delStepBorder();//删除结束点的触发Over画出来的提示小圆
					tempLine.x2 = x;
					tempLine.y2 = y;
					if(3 == dancer.opreateNum) {
						//invisible = false;	
						opacity  = 1;
					}
					else {
						//invisible = true;	
						opacity = 0.1;
					}
					tag = linePropertyReady(tempLine.startDir, tempLine.endDir, dancer.opreateNum, listId, opacity)
					lineStartJudge.pos.length = 0;
					tempLine.tempRlt.lineTag = tag;	
					rltArr = dba.stepRlt[listId[0]].rltArr;
					rltArr.push({
							"type":"start",
							"flwType" : dancer.opreateNum,
							"startPoint" : tempLine.tempRlt.startPoint,
							"endPoint" : lineStartJudge.direction,
							"lineTag" : tag,
							"curPos" : tempLine.tempRlt.pos,
							"tagPos" : lineStartJudge.pos,
							"tagId" : [listId[0], listId[1]]
					});
					dba.stepRlt[listId[1]].rltArr.push({
							"type":"end",
							"flwType" : dancer.opreateNum,
							"startPoint" : tempLine.tempRlt.startPoint,
							"endPoint" : lineStartJudge.direction,
							"lineTag" : tag,
							"curPos" : lineStartJudge.pos,
							"tagPos" :	tempLine.tempRlt.pos,
							"tagId" : [listId[0], listId[1]]
					})
					//添加连线关系，在defaultStepDel基础上，根据连线的性质对部分数据做修改。
					stepNum = dba.stepRlt[listId[0]].stepNum;
					dba.stepDel[stepNum] = dba.stepDel[stepNum] || [];
					tempStepDel = deepClone(dba.defaultStepDel);
					tempStepDel[3] = 3 == dancer.opreateNum?"N":4==dancer.opreateNum?"B":"M";
					tempStepDel[6] = dba.stepRlt[listId[1]].stepNum;
					dba.stepDel[stepNum].push(tempStepDel)
					//根据listID[0]的rltArr关系，判断是否有多个N，若有的话就添加SQL分支的图标。
					for(var i = 0, nRlt = 0, len = rltArr.length; i < len; i++) {
						if("start" == rltArr[i].type 
							&& ("N" == rltArr[i].flwType || 3 == rltArr[i].flwType)) {
							nRlt++;	
						}	
					}
/*					if(!dba.stepRlt[listId[0]].addImg && nRlt > 1) {
						dancer.drawAddImg(listId[0], stepNum);
						dba.stepRlt[listId[0]].addImg = true;
					}*/
					tempLine.tag = tag;
					tempLine.id = tag.id;
					//变量初始化。
					goFlow.judge.lineDrag = false;
					dancer.opreateNum = 0;	
					listId.length = 0;
				}
				else {
					//错误提示
					tipFont.innerHTML = "错误操作!设置连线的终点时，鼠标应放到小红圈上再点击即可。";
					tipWrap.className = "footer show-block";
				}	
			}
		}
		_body.onmouseover = function(event) {
			event = event || window.event;
			tag = getEventTag(event);
			switch(tag.className) {
/*				case "info-move-left":
					if(0 != dba.currentLi) {
						tag.style.cursor = "pointer";
						dba.dirLeft.style.display = "block";
					}
					break;
				case "info-move-right":
					if(2 != dba.currentLi) {
						tag.style.cursor = "pointer";
						dba.dirRight.style.display = "block";
					}
					break;*/
				case "info_dir":
					tag.style.display = "block";
					break;
				case "step-x":
					tag.className = "step-x step-x-red";
					break;
				case "mes-td-normal":
					tag.className = "mes-td-selected";
					break;
				default:
					break;	
			}
		}
		_body.onmouseout = function(event) {
			event = event || window.event;
			tag = getEventTag(event);
			switch(tag.className) {
				case "info_dir":
					tag.style.display = "none";
				case "step-x step-x-red" :
					tag.className = "step-x";
					break;
				case "stepConnectTip":
					tag.className = "stepConnectTip hide";
					break;
				case "mes-td-selected":
					tag.className = "mes-td-normal";
				default:
					break;	
			}
		}
		/**
		 *keyup绑定函数，主要用来绑定快捷键
		*/
		_body.onkeyup = function(event) {
			event = event || window.event;
			var skeyCode = 	event.keyCode;
			var curRlt, id;
			if('' != dba.focusTag) {
				return false;	
			}
			switch(skeyCode) {
				case 81:          // Q，N关系
					if(3 != dancer.opreateNum) {
						drawSwitch(dancer.opreateNum);
					}
					dancer.oprModel[dancer.opreateNum].parentNode.className = "pic-li";
					dancer.opreateNum = 3;
					dancer.oprModel[dancer.opreateNum].parentNode.className = "cur-model-li";
					lineStartJudge.start = true;
					goFlow.judge.lineDrag = true;
					break;	
				case 87:          // W, M关系
					dancer.oprModel[dancer.opreateNum].parentNode.className = "pic-li";
				   if(4 != dancer.opreateNum) {
						drawSwitch(dancer.opreateNum);
					}
					dancer.opreateNum = 4;
					dancer.oprModel[dancer.opreateNum].parentNode.className = "cur-model-li";
					lineStartJudge.start = true;
					goFlow.judge.lineDrag = true;
					break;
				case 69:          // E，B关系
					dancer.oprModel[dancer.opreateNum].parentNode.className = "pic-li";
					if(5 != dancer.opreateNum) {
						drawSwitch(dancer.opreateNum);
					}
					dancer.opreateNum = 5;
					dancer.oprModel[dancer.opreateNum].parentNode.className = "cur-model-li";
					lineStartJudge.start = true;
					goFlow.judge.lineDrag = true;
					break;	
				case 65:          // A，正常步骤
				case 68:          // D，动态步骤
					dancer.oprModel[dancer.opreateNum].parentNode.className = "pic-li";
					if(65 == skeyCode ) {
						if(1 != dancer.opreateNum) {
							drawSwitch(dancer.opreateNum);
						}
						dancer.opreateNum = 1;	
					}
					else {
						if(2 != dancer.opreateNum) {
							drawSwitch(dancer.opreateNum);
						}
						dancer.opreateNum = 2;
					}
					dancer.oprModel[dancer.opreateNum].parentNode.className = "cur-model-li";					
					dancer.stepClick.style.cssText = "left:"+(dba.mousePos .x - 10 - dancer.canvasWrap[0]) + "px;top:"
																	+ (dba.mousePos .y - 10 -  dancer.canvasWrap[1])+"px";
					dancer.stepClick.className = "stepclick show-inline";
					dba.moveTag = dancer.stepClick;
					dba.moveTag.style.cursor = "default";
					moveDefault();
					break;	
				case 113:  //F12
					if(0 != clickArr.length && "img" == clickArr[0].type){
						zr.modShape(clickArr[0].id,{
							style : {
								text : ''	
							}	
						});
						zr.refresh();
						showStepInput(clickArr[0].stepName, stepArr[clickArr[0].id][0], stepArr[clickArr[0].id][1]);	
					}
					break;
				case 46:    //delete
					len = clickArr.length;	
					if(0 == len) {
						return false;	
					}
					else {
						for(var i = 0; i < len; i++) {
							tag = clickArr[i];
							switch(tag.type) {
								case "brokenLine":
									brokenPoints[tag.id].length = 0;
									//删除开始步骤的该线关系。
									tagRlt = dba.stepRlt[tag.startStep].rltArr;
									_removeRltTag(tagRlt, "start", tag, false);
									//删除结束步骤的该线关系.
									tagRlt = dba.stepRlt[tag.endStep].rltArr;
									_removeRltTag(tagRlt, "end", tag, false);
									zr.delShape(tag.id)
									break;
								case "img":
									tagRlt = dba.stepRlt[tag.id].rltArr;
									rltLen = tagRlt.length;
									id = tag.id;
									if(0 == rltLen) {
										
									}
									else {
										for(var j = 0; j < rltLen; j++) {
											curRlt = tagRlt[j];
											if("start" == curRlt.type) {
												_removeRltTag(dba.stepRlt[curRlt.tagId[1]].rltArr, "end", curRlt.lineTag, true);	
											}	
											else {
												_removeRltTag(dba.stepRlt[curRlt.tagId[0]].rltArr, "start", curRlt.lineTag, true);		
											}
											zr.delShape(curRlt.lineTag.id)
										}	
									}
									if(1 == solidArr[stepObj[id][0]].length) {
										solidArr.splice(stepObj[id][0], 1);	
										if(1 == solidArr.length) {
											solidArr.length = 0;	
										}
									}
									else {
										solidArr[stepObj[id][0]].splice(stepObj[id][1], 1);	
									}
									zr.delShape(id);
									dba.stepRlt[id] = {};
									solidSort();
									break;	
							}	
						}
					}
					clearClicked();	
					break;
				case 27:   //esc
					if(0 != dancer.opreateNum) {          //操作类型退出
						drawSwitch(dancer.opreateNum);
						dancer.oprModel[dancer.opreateNum].parentNode.className = "pic-li";
						dancer.oprModel[0].parentNode.className = "cur-model-li";
						dancer.opreateNum = 0;
						goFlow.judge.lineDrag = false;
						lineStartJudge.start = false;
/*						if(shape.showTip) {
							delStepBorder();	
							shape.showTip = false;
							lineStartJudge.stepId = '';
						}*/
					}
					
					if(dancer.showStepRelation) {    //步骤关系线段显示退出.
						while(dba.eyaBrokenPointsId >= 8000) {
							zr.delShape(dba.eyaBrokenPointsId--);	
						}
						_truthStrong.innerHTML = "C";
						dancer.showStepRelation = false;
						dba.eyaBrokenPointsId = 8000;
						zr.refresh();
					}
					break;	
			}
			/**
			 *删除关系对象中的元素.
			 *@param {Boolean} deep false:表面找到第一个匹配就退出;true：找到第一个后仍继续查找，因为相同的2个步骤可能存在同向流转关系。
			*/
			function _removeRltTag(tagRlt, type, lineTag, deep) {
				var rltLen = tagRlt.length;
				for(var j = 0; j < rltLen; j++) {
					curRlt = tagRlt[j];
					if(type == curRlt.type && lineTag == curRlt.lineTag) {
						tagRlt.splice(j, 1);
						if(!deep) {
							break;	
						}
					}
				}
			}
		}
		startTip.inputTag.onkeyup = function(event) {;
			startTip.start(event);
		}
		//屏蔽选中文字
		_body.onselectstart = function (event){
			if(window.event){
				event = window.event;
			}
			try{
				var the = event.srcElement;
				if (!((the.tagName == "INPUT" && the.type.toLowerCase() == "text") || the.tagName == "TEXTAREA")){
					return false;
				}
				return true;
			} catch (e) {
				return false;
			}
		}
		flwName = $("flwName");
		flwName.onblur = function() {
			if('' == dba.flow && "点击命名新流程" != this.value && undefined == dancer.opreateNum) {
				flowProgressSpan[0].className = "step-finish-one";
				dancer.drawStart();
				dancer.opreateNum = 0;
				dancer.oprModel[0].parentNode.className = "pic-li cur-model-li";
				dba.named = true;
				dba.flow="newflow";
			}	
		}
		flwName.onchange = function() {
			$("lcName").value = this.value;	
		}
		$("lcName").onchange = function() {
			flwName.value =  this.value;	
		}
		stepInput.onblur = function() {

		}
	}			
	//php数据数据初始化。
	goFlow.init.data = function(readyData) {
		dba.flow = readyData.flow;
		startTip.data = readyData.flwNameData;
		//here
		console.log(dba.flow)
		if("" != dba.flow) {
			//dba.named = true;
			this.start(readyData);
		}
		else {
			dba.allGs = readyData.allGs;
			this.newFlwInit();	
		}

	}
		//整个过程开始函数，用于页面打开和公司选择后调用。
	goFlow.init.start = function(readyData) {
		dba.currentGs = gongSiName.innerHTML;
		dba.allGs = readyData.allGs;
		dba.operateType = readyData.operateType;
		var tempGs;
		//如果选择公司下面没有则调用公用的流程。
		if(undefined != readyData.steps[dba.currentGs]) {
			dba.receive(readyData.steps[dba.currentGs], readyData.stepRelation[dba.currentGs], radyData.stepCheck)	
		}
		else {
			tempGs = '00000000'
			if(undefined == readyData.steps["00000000"]) {
				tempGs = '00000002';	
			}
			dba.receive(readyData.steps[tempGs], readyData.stepRelation['00000000'], readyData.stepCheck);
			dba.currentGs = tempGs;
		}
	}
	goFlow.init.newFlwInit = function() {
			//this.flwTip.style.display = "block";
				flowProgressSpan[0].className = "step-finish-one";
				dancer.drawStart();
				dancer.opreateNum = 0;
				dancer.oprModel[0].parentNode.className = "pic-li cur-model-li";
			//dba.named = true;
				dba.flow="newflow";
	}
	/**DBA函数**/
	function Data(){
		this.gs = $("gongsi");
		this.line = false;//用来判断某条主分支下面是否将分支走完。
		this.canMove = false;
		this.curCheckStep;//当前主分支的。
		this.colorNum = 0;
		this.menuTag = $("menu");
		this.flwModel = $("flw");
		this.flwCont = $("flw_cont");
		this.qx_cont = $("qx_cont");
		this.busCont = $("bus_cont");
		this.contArr = [this.flwCont, this.qx_cont, this.busCont];
		this.infoTag = $("info");
		this.dataContent = $("info");
		this.stepModel = tableTag($("stepModel"));//步骤关系模板
		//this.stepModel = $("stepModel");//步骤关系模板
		this.focusTag = '';   // 当前获取焦点对象。
		this.dirLeft = $_class("info-move-left", "div")[0];
		this.dirRight = $_class("info-move-right", "div")[0];
		this.liMove = $_class("info-content-div", "div")[0];
		this.infoTitle = $("info_title");
		this.busMode = $("bus");
		this.liTags = $_class("info_li", "li");
		this.currentLi = 0;
		this.qxdel = $("qxdel");
		this.qx_input = tableTag($("qxModel"));
		this.defaultHeight = [383,291,420];
		this.plModel = $("piliang");
		this.ie = !+"\v1"; 
		this.infoMove = $("infoMove");
		this.monitoring = {};//监控属性对象
		this.saveBut = $("saveinfo");
		this.hasChild = false;
		this.gnLi = $_class("gn_li","li");
		this.moveCont = false;//是否正在移动步骤、业务、权限3个内容、
		this.eyaBrokenPointsId = 8000;
		this.addImgCont = []; //添加了addImg图形的结合
		this.step = [];
		this.stepDel = [];
		this.stepIds = [];
		this.stepRlt = [];
		this.lineRlt = [];
		this.defaultStepInfo = {
			0 : "",1 : "1800-01-01",2 : "9999-12-31",3 : "",4 : "",5 : "有效",6 : "",7 : "",8 : "",9 : "",	10 : "2880",11 : "MSGS",12 : "",
			13 : "0",14 : "0",15 : "0",16 : "",17 : "",18 : "", "docid":"", "prvid":""
		}
		this.defaultStepDel = {
			0 : "1800-01-01",1 : "9999-12-31",2 : "",3 : "",4 : "1",5 : "00000000",6 : "",7 : "0",8 : "", 9:"", 10:"0", 11 : "0"
		}
		this.defaultBusInfo = {
			0 : "系统自动生成",1 : "系统自动生成",2 : "",3 : "",4:"", 5 : "1800-01-01",6 : "9999-12-31",7 : "",8 : "_blank",9 : "", 10:"_blank", 11:"30", 12 : "",
			13:"BID,BOHRID", 14:"", 15:"MB", 16: "MSGS"	
		}
		this.sqlRelationDiv = $_class("step-relation hide", "div")[0];
		this.stepContinue = 1;
		this.flwRelConfig = {     //右侧配置界面步骤点击相应对象。
			//flwWrapDiv : $_class("config-relation-div", "div")[0],
			//rightWrapDiv : $_class("config-permissions-div", "div")[0],
			currSpan : ''
		};
		this.html = require('zrender/tool/html');
	}
	Data.prototype = {
		//接受数据，并调整为需要的数据。
		receive : function(step, stepDel, stepCheck) {
			var i, j, tempSteps;
			var tempVal, _line;
			var rlt = 0,m = 0, firstNext = true;
			var tempFlow = [];//用来存储流程的步骤号、注意多分支的处理。
			var relKey = 0, curCheckStep;
			var	_rltArr = [];//第一个分支N的流转步骤
			var _stepArr = [], stepNum;//存储步骤号
			var relation = [];//用以存储各个步骤的关系。
			var loopRaltion = [];//回路关系集合，用于判断有回路步骤每个N和A是否check了
			this.step = step;
			this.stepDel = stepDel;
			this.stepCheck = stepCheck;
			for(i in this.step) {
				_stepArr.push(i);	
			}
			var stepLen = _stepArr.length;
			for(stepNum = 0; stepNum < stepLen; stepNum++) {
				i = _stepArr[stepNum];
				if(0 == relKey && undefined ==relation[relKey]) {
					relation[relKey] = "s_"; 
					relation[relKey] +=  this.step[i].stpid;
				}
				//排除全新控制步骤或者无流程步骤。
				if(undefined != relation[relKey]) {
					if(!stepCheck[this.step[i].stpid].checked) {
						tempSteps = stepDel[this.step[i].stpid];
						for(var j in tempSteps) {
							if(!tempSteps[j].checked) {
								if("N" == tempSteps[j].rlttp || "A" == tempSteps[j].rlttp) {
									rlt++;
									firstNext = false;	
									_rltArr.push(tempSteps[j].stpchid)
								}
							}
						}
						if(1 == rlt) {
							relation[relKey] = relation[relKey] + "_" + _rltArr[0];
							//当只有一个流转，且流转到的步骤吧不是当前步骤的下一个步骤时，调整一下step数组的位置。
							for(delNum = 0; delNum < stepLen; delNum++) {
								if(_rltArr[0] == _stepArr[delNum] && (stepNum+1)!=delNum) {
									_stepArr.splice(delNum, 1);
									_stepArr.splice(stepNum+1, 0, _rltArr[0]);	
								}	
							}
						}
						else {
							tempVal = relation[relKey]; 
							for( ; m < rlt; m++) {
								_curCheckStep = _rltArr[m];
								do{
									relation[relKey] = tempVal + "_" + _rltArr[m]; 
									_getNext(_rltArr[m]);
									relKey++;
								}while(_line);
							}
						}
						firstNext = true;	
					}
					rlt = 0
					_rltArr.length = 0;
				}
			}
			for(var i in relation) {
				//break;
				//console.log(relation[i]);	
			}
			this.tidyStep(relation);
			function _getNext(step) {
				var i, tempSteps, m, n, firstNext = true, rlt = 0;
				var k, relLen, allCheck, head;
				var otherLine = false, _firstNextNum;
				var tempArray = [], tempLen, j;
				var tempVal = relation[relKey];
				var loopJuadge = false;
				tempSteps = stepDel[step];
				//首先判断该步骤是否已经确定
				if(stepCheck[step].checked) {
					_line = false;
					return true;	
				}	
				else {			
					for(i in tempSteps) {
						if(0 == tempSteps[i].stpchid || ("N" == tempSteps[i].rlttp && !stepCheck[tempSteps[i].stpchid].checked)) {
							if(0 == tempSteps[i].stpchid && 0 == tempSteps[i].checked) {
								otherLine = true;
								m = i;
							}
							if("N" == tempSteps[i].rlttp && 0 != tempSteps[i].stpchid) {
								if(firstNext) {
									n = i;
									_firstNextNum = tempSteps[i].stpchid;
									//针对第一个下一步，做一下判断，避免回路带来的死循环。
									if(0 <= relation[relKey].indexOf(_firstNextNum)) {
										tempSteps[i].loop = true;
										otherLine = true;
										loopJuadge = true;
										continue;
									}
								}
								rlt++;
								firstNext = false;	
								otherLine = false;
							}
						}
						else {
							tempSteps[i].checked = true;	
						}
					}				
					//一个分支到达归档，判断该条分支走完。
					if(0 == rlt && otherLine) {
						//可以确定这个步骤是一个终点。
						if(!loopJuadge) {
							tempSteps[m].checked = true;
							stepCheck[step].checked = true;
						}
						relation[relKey] = tempVal+"_0";
						//反向查找
						tempArray = relation[relKey].split("_");
						tempLen = tempArray.length;
						for(j = (tempLen - 2); j > 0; j--) {
							if(curCheckStep == tempArray[j]){
								head = relation[relKey].split(_curCheckStep)[0] + _curCheckStep;
								if(_checkStep(curCheckStep, "special", tempArray[j + 1], head)) 
								if(_checkStep(curCheckStep)) {
									_line = false;//这条分支结束。
									stepCheck[_curCheckStep].checked = true;	
									return;	
								}
								else {
									_line = true;
									return;	
								}
							}			
							else if(!stepCheck[tempArray[j]].checked) {
								if(!_checkStep(tempArray[j], "normal")) {
									_line = true;
									return true;	
								}	
							}
						}
					}
					if(rlt){
						if(!otherLine) {
							relation[relKey] = tempVal + "_" +_firstNextNum; 
							_getNext(_firstNextNum);	
						}
						//如果有，优先处理0再循环处理N。
						else if(otherLine){
							tempSteps[m].checked = true;
							relation[relKey] = tempVal+"_0";
							_line = false;
							return true;
						}
					}
					else {
						tempArray = relation[relKey].split("_");
						tempLen = tempArray.length;	
						tempSteps = stepDel[tempArray[tempLen - 1]];	
						for(i in tempSteps) {
							if("N" == tempSteps[i].rlttp && 0 != tempSteps[i].stpchid) {
								for(k = 0, relLen = relation.length; k < relLen; k++) {
									if(undefined != relation[k] && 0 <= relation[k].indexOf(tempSteps[i].stpchid)) {
										relation[relKey] = tempVal + "_"+ tempSteps[i].stpchid;
										relKey++;
										break;
									}	
								}
							}
						}
						//向上查找
						for(k = tempLen - 1; k > 0; k--) {
							if(_curCheckStep == tempArray[k]){
								if(_checkStep(_curCheckStep)) {
									if(_checkStep(_curCheckStep, "normal")) {
										_line = false;//这条分支结束。
										stepCheck[_curCheckStep].checked = true;
									}
									//判断所以的分支是否都走完。
									for(i = 0, j = _rltArr.length; i < j; i++) {
										if(0 != _rltArr[i] && !stepCheck[_rltArr[i]].checked) {
											allCheck = false;
											return true;
										}	
									}	
									allCheck = true;
								}
								else {
									_line = true;
									return true;	
								}
							}			
							else if(!stepCheck[tempArray[k]].checked) {
								if(!_checkStep(tempArray[k], 'normal')) {
									_line = true;
									return true;	
								}	
							}
							if(allCheck) {
								stepCheck[tempArray[k]].checked = true;	
							}
						}
						_line = false;
						return true;	
					}
				}
			}
			function _checkStep(step, type, num, head) {
				var tempStep = stepDel[step];
				var tempArr = [] ,j ,i ,arrLen, relLen;
				for(var i in tempStep) {
					if('N' == tempStep[i].rlttp || 'A' == tempStep[i].rlttp) {
						if(0 != tempStep[i].stpchid && !stepCheck[tempStep[i].stpchid].checked && !tempStep[i].loop) {
							return false;
						}
						else if(undefined != num && num != tempStep[i].stpchid){
							tempArr.push(tempStep[i].stpchid);
						}
					}
				}
		
				if("special" == type) {
					for(j = 0, arrLen = tempArr.length; j < arrLen; j++) {	
						for(i = 0, relLen = relation.length; i < relLen; i++) {
							if(0 <= relation[i].indexOf(tempArr[j])) {
								relKey++;
								relation[relKey] = head + "_"+ tempArr[j] + relation[i].split(tempArr[j])[1];
								break;	
							}	
						}	
					}
				}
				stepCheck[step].checked = true;
				tempArr.length = 0;
				return true;
			}
		},
		/**调用画图函数画图**/
		/*设计思路：data只负责计算每个步骤的位置，然后将这些数据扔给画图器；
		/*采用从主流程0步骤往上画的思想。
		/*******************/
		tidyStep : function(relation) {
			var i, j, h, k, m = 1, n = 0, rlt = 0;//rlt用来存储有多少个流转
			var mainFlw, flws, norepeat = "s";//主流程。
			var tempSteps, speciLine = {};
			var startleft, tempLeft, tempTop;
			var tempArr = [], inFirstLine = false;
			var relStep = [], relMax = 0;//最终每一行的步骤号数组和最大列数
			var lineAdj = [];//用来存储折现的位置，避免重叠。
			var pathLeft, pathRight ;//用来记录左右两边的最大值。
			var a, b, maxNum;
			lineAdj[0] = -15;
			lineAdj[1] = 15;
			//先确定最长流程作为主流程，若有多个同长度流程，选第一个作为主流程。
			for(i in relation) {
				if(rlt < relation[i].length) {
					rlt = relation[i].length;
					m = i;	
				}
				relation[i] = relation[i].split("_");
				relation[i] = relation[i].splice(1, relation[i].length - 1);
			}
			//去除重复的步骤号，并调整位置。
			mainFlw = relation[m];
			for(i = 0, rlt = mainFlw.length; i < rlt; i++) {
				relStep[n] = [];
				for(j in relation) {
					if(undefined ==  relation[j][i] || 0 == relation[j][i]) {
						continue;	
					}
					else{
						if(j == m || (j != m && !inArray(mainFlw, relation[j][i]))) {
							relStep[n].push(relation[j][i]);
							if(0 > norepeat.indexOf(relation[j][i])) {
								norepeat = norepeat + "_" + relation[j][i] + "_" + n;
							}else {
								tempArr = norepeat.split(relation[j][i]);
								norepeat = tempArr[0] + relation[j][i] + "_" + n + tempArr[1].substr(2, tempArr[1].length-2);
								k = tempArr[1].split("_")[1];
								for(h in relStep[k]) {
									if(relation[j][i] == relStep[k][h]) {
										relStep[k].splice(h, 1);
										break;
									}	
								}
								relMax = 0;	
								for(h in relStep) {
									if(relMax < relStep[h].length) {
										relMax = relStep[h].length;	
										maxNum = h;
									}
								}
							}
						}
					}
					if(relMax < relStep[n].length) {
						relMax = relStep[n].length;	
						maxNum = n;
					}
				}
				n++;
			}
			norepeat = '';
			//已有流程转图形。
			dancer.opreateNum = 0;
			dancer.drawStart();
			flowToPic(relStep, relMax, mainFlw, maxNum);
			mainFlw.length = 0;
			relation.length = 0;
			return;
		},
		//步骤、业务、权限数据设计思想：
		/* 对于新建流程，可能会重复修改数据，固将新建的信息存储到cookie中，减少读取数据库次数。
		**对于cookie中没有的数据采用如下方式向页面添加数据。
		** 1，先去克隆步骤，业务，权限表格模板；
		** 2，步骤信息在页面第一次读取时已从数据库中出去；
		** 3，业务和权限因为数据量较大，固使用ajax获取。
		** 4，赋值：取数时，对于每个表单中的input或者select通过class的方式获取，从数据库取数时就叫数字属性交给数字无需额外的Id来赋值
		*******************************/
		flwData : function(type) {
			var clNode = this.flwModel.cloneNode(true);
			this.flwCont.appendChild(clNode);		
			var valTag = [], tempTag, i=0, tmepLen;
			var tempTr, tempTd, k = 1;
			var index, tempSteps;
			var curDel, delLen, j = 0;
			var relTable, tempTr, tempTd, i;
			tempTag = clNode.getElementsByTagName("*")
			valTag = this.getEle(tempTag);
			observer.setPuber(valTag);//绑定监听
			var stepNum = this.stepRlt[this.currStep].stepNum;
			this.setData(valTag, this.step[stepNum]);//赋值
			this.flwCont.appendChild(clNode);
			clNode.style.display = "block";
			//插入流转信息
			curDel = this.stepDel[stepNum];	
			if(undefined != curDel) {
				clNode = this.stepModel.cloneNode(true);
				valTag.length = 0;
				for(j = 0, delLen = curDel.length; j < delLen; j++) {
					tempTr = this.infoRel.insertRow(k);
					var tds = clNode.getElementsByTagName("td");
					for(n = 0; n < tds.length; n++) {
						tempTd = tempTr.insertCell(n);
						tempTd.innerHTML = tds[n].innerHTML;
						childs = tempTd.getElementsByTagName("*");
						m = childs.length;
						i = 0;
						while(i < m) {
							currentNode = childs[i];
							if(3 != currentNode.nodeType && !inArray(["IMG","DIV","SPAN","OPTION"], currentNode.nodeName)) {
								valTag.push(currentNode);
							}
							i++;	
						}
						
					}
					this.setData(valTag, this.stepDel[stepNum][j]);
					valTag = [];
					k++;
				}
				tempTag = this.infoRel.getElementsByTagName("*")
				valTag = this.getEle(tempTag);
				observer.setPuber(valTag);//绑定监听
			}
			this.infoTag.style.height = 365 + j * 27 + "px";
			this.defaultHeight[0] = 340 + j * 27;
			if(!this.moveCont) {
				dba.liMove.style.left = "0px";
			}
			if(undefined == type) {
				this.currentLi = 0;
			}
			this.dirLeft.className = "info-move-left show-block";
			this.dirRight.className = "info-move-right hide";
			this.infoTag.className = "info-wrap show-block";
			this.flwCont.style.height = this.defaultHeight[0] + "px";
		},
		busData : function(type) {		
			var tempTag, valTag, j;
			var tempTag, data;
			var stepNum = this.stepRlt[this.currStep].stepNum;
			//计算出当前步骤具体高度。
			if(undefined == this.infoRel) {
				j = 0;
			}
			else {
				j = this.infoRel.rows.length - 1;	
			}
			this.defaultHeight[0] = 340 + j * 27;
			var clNode = this.busMode.cloneNode(true);
			this.busCont.appendChild(clNode);
			tempTag = this.busCont.getElementsByTagName("*");
			valTag = this.getEle(tempTag);
			observer.setPuber(valTag);//绑定监听
			this.getBusData(valTag, dba.step[stepNum].docid, type);
			dancer.setInfoDir(dba.currentLi);
			clNode.style.display = "block";
		},
		qxMsData : function(type) {
			var j;
			if(undefined == this.infoRel) {
				j = 0;
			}
			else {
				j = this.infoRel.rows.length - 1;	
			}
			this.defaultHeight[0] = 340 + j * 27;
			var clNode = this.qxdel.cloneNode(true);
			this.qx_cont.appendChild(clNode);
			clNode.style.display = "block";
			if(undefined == this.currentPrvid) {
				this.currentPrvid = undefined != this.stepCheck?this.stepCheck[this.currStep].prvid:this.stepRlt[this.currStep].prvid || 0;
			}
			if(0 !== this.currentPrvid) {
				request("yewu.php",{
					data:"prvid="+dba.currentPrvid+"&cohrid="+dba.currentGs,
					method: 'GET',
					datatype:'JSON',
					async:'true',
					success: function(data) {
						data = eval('(' + data + ')');
						tempTag = clNode.getElementsByTagName("*");
						valTag = dba.getEle(tempTag);
						dba.setData(valTag, data);
						dba.qxData(data[0], type);
					},
					failure: function(data1) {
						alert("权限信息获取失败");	
					}
				});	
			}
			else {
				dba.qxData(0, type);
			}
		},
		qxData : function(oid, type) {
			var tempTag, valTag;
			var fragment = ceDfg();
			var contentDiv = ce("div");
			var tempTable = ce("table");
			contentDiv.innerHTML = '<table cellpadding="0" cellspacing="0" style="text-align:center;"><tr id="info_qx_head"><td width="80px" height="25px">开始日期</td><td width="90px">结束日期</td><td width="105px">组织代码</td><td width="115px">权限类别</td><td width="90px">权限选择</td><td width="225px">SQL手动条件</td><td width="50px">备注</td><td width="55px">检查</td><td width="35px">定界</td><td width="30px">删除</td></tr><tr><td></td></tr></table>';
			this.qx_cont.appendChild(contentDiv);
			contentDiv.className = "info_qx_tabHead";
			contentDiv = ce("div");
			contentDiv.className = "info_qx_div";
			request("yewu.php",{
				data:"oid="+oid,
				method: 'GET',
				datatype:'JSON',
				async:'true',
				success: function(data) {
					contentDiv.innerHTML = data;
					fragment.appendChild(contentDiv);
					this.qx_cont.appendChild(fragment);
					tempTag = dba.qx_cont.getElementsByTagName("*");
					valTag = dba.getEle(tempTag);
					observer.setPuber(valTag);//绑定监听
				},
				failure: function(data1) {
					alert("权限信息获取失败");	
				}
			});			
			if(undefined == type) {		
				dba.liMove.style.left = "-1840px";
				dba.currentLi = 2;
				dancer.setInfoDir(dba.currentLi);
				dba.infoTag.className = "info-wrap show-block";
			}
		},
		getBusData : function(valTag, docid, type) {
			//取该步骤对应的业务数据
			//加载业务数据
			if('' != docid) {
				request("yewu.php",{
					data:"docid="+docid,
					method: 'GET',
					datatype:'JSON',
					async:'true',
					success: function(data) {
						data = eval('(' + data + ')');
						dba.currentPrvid = data.prvid;
						dba.setData(valTag, data); //因ajax取数有延迟，故在此重新获取赋值
					},
					failure: function(data1) {
						alert("业务信息获取失败");	
					}
				});	
			}
			else {
				data = deepClone(this.defaultBusInfo);  // 新建步骤，业务描述用默认值。
				dba.setData(valTag, data);	
			}			
			if(undefined == type) {		//如果是通过check只需获取数据，即流程、业务、权限切换时并不需要再去做这样的调整
				dba.liMove.style.left = "-920px";
				dba.currentLi = 1;
				dancer.setInfoDir(dba.currentLi);
				dba.infoTag.className = "info-wrap show-block";
			}
		},
		setSelIndex : function(sel, val) {
			var opts = sel.getElementsByTagName("option");
			var len = opts.length;
			for(var i =0; i < len; i++) {
				if(opts[i].value == val) {
					opts[i].setAttribute("selected", true);	
				}	
			}
		},
		getEle : function(tempTag) {
			var valTag = [];
			var j, i = 0;
			for(j = 0, tmepLen = tempTag.length; j < tmepLen; j++) {
				if(tempTag[j] !=null && undefined != tempTag[j].className) {
					if("flw_input" == tempTag[j].className || 0 <= tempTag[j].className.indexOf("flw_input") || "flw_check" == tempTag[j].className){
						valTag.push(tempTag[j]);
					}
					if("info_add" ==  tempTag[j].className) {
						this.infoRel = tableTag(tempTag[j]);	
					}
				}
			}
			return valTag;
		},
		getEleForRight : function(tempTag) {
			var valTag = [];
			for(var j = 0, tmepLen = tempTag.length; j < tmepLen; j++) {
				if(inArray(['INPUT', 'SELECT', 'TEXTAREA'], tempTag[j].nodeName)) {
					valTag.push(tempTag[j])	
				}
			}
			return valTag;
		},
		setData : function(valTag, data) {
			var _index, i, j, len;
			var curGs, innerHtml = '';
			for(i in valTag) {
				switch(valTag[i].tagName) {
					case "INPUT":
						if("checkbox" == valTag[i].getAttribute("type") && 1 == data[i]) {
							valTag[i].checked = true;
							continue;
						}				
						if(null !== data[i]) {
							valTag[i].setAttribute("value", data[i]);
						}
						break;
					case "TEXTAREA":
						valTag[i].value = data[i];
						break;
					case "SELECT":	
						if(0 <= valTag[i].getAttribute("name").indexOf("OHRID")) {
								allGs = dba.allGs;
								len = allGs.length;
								for(j = 0; j < len; j++) {
									curGs = allGs[j];
									if(data[i] == curGs.id) {
										innerHtml = innerHtml + '<option value="'+curGs.id+'" selected>'+allGs[j].id +':'+curGs.name +'</option>';	
									}
									else {
										innerHtml = innerHtml + '<option value="'+curGs.id+'">'+allGs[j].id +':'+curGs.name +'</option>';
									}
								}
								valTag[i].innerHTML = innerHtml;
								break;
						}
						this.setSelIndex(valTag[i], data[i]);
					break;
				}
			}	
		},
		//添加流转步骤行。
		newFlwLine : function() {
			var data;
			var clNode = this.stepModel.childNodes[0].cloneNode(true);
			var tempTag = clNode.getElementsByTagName("*")
			var valTag = this.getEle(tempTag);
			var rowNum = this.infoRel.rows.length;
			var tempTr = this.infoRel.insertRow(rowNum);
			var tempTd, n;
			var tds = clNode.getElementsByTagName("td");
			for(n = 0; n < tds.length; n++) {
				tempTd = tempTr.insertCell(n);
				tempTd.innerHTML = tds[n].innerHTML;	
			}	
			dba.defaultHeight[0] +=  27; 
			data = '("18000101","99991231","","","","","","","","","","300","'+dba.flow+'","'+this.currStep+'")';
			observer.insert("flw",rowNum, data);//对于新增的步骤配置和权限通过这种方式来表明数据变更、
			tempTag = this.infoRel.getElementsByTagName("*")
			valTag = this.getEle(tempTag);
			observer.setPuber(valTag);//绑定监听
			this.flwCont.style.height = this.defaultHeight[0] + "px";
			this.infoTag.style.height = parseInt(realStyle(dba.infoTag, "height")) + 27 + "px";
			dba.saveBut.style.display = "block";
		},
		//添加权限行
		addQxModel : function(tag) {
			var font = tag.innerHTML;
			var clNode, tempTag, tempTr, tds, tempTd;
			switch(font) {
				case "批量添加用户":
					this.qx_cont.appendChild(this.plModel);
					$("typedel").innerHTML = "工号：(每个工号之间请用英文输入状态 , 分开)";
					this.plModel.style.display = "block";
					this.plType = "U";
					break;
				case "批量添加用户组":
					this.qx_cont.appendChild(this.plModel);
					$("typedel").innerHTML = "用户组：(每个用户组之间请用英文输入状态 , 分开)";
					this.plModel.style.display = "block";
					this.plType = "G";
					break;
				case "单个添加":
					if(undefined == this.qxTable) {
						this.qxTable = $("qx_table");	
					}
					clNode = this.qx_input.firstChild.cloneNode(true);
					tempTag = clNode.getElementsByTagName("*");
					rowNum = this.qxTable.rows.length;
					tempTr = this.qxTable.insertRow(rowNum);
					tds = clNode.getElementsByTagName("td");
					for(n = 0; n < tds.length; n++) {
						tempTd = tempTr.insertCell(n);
						tempTd.innerHTML = tds[n].innerHTML;
						tempTd.style.borderBottom = "1px solid #EBFADE";	
					}
					firstTr = this.qxTable.rows[1];
					break;
				default:
					break;	
			}
		},
		addQxLine : function() {
			var qx, qxSql, timer_1, timer_2, qxType, clNode;
			var valTag, tempTag, sendData;
			var tempTr, tempTd, n, rowNum, firstTr;
			if(undefined == this.qxTable) {
				this.qxTable = $("qx_table");	
			}
			qx = $("ug").value;
			qxSql = $("plsql").value;
			$("ug").value = '';
			$("plsql").value= '';
			timer_1= $("pl_start").value;
			timer_2 = $("pl_end").value;
			var i, arrLen, data = [];
			data[0] = timer_1;
			data[1] = timer_2;
			data[2] = this.gs;
			data[3] = this.plType;
			if('' == qx) {
				if("U" == this.plType) {
					alert("请至少输入一个工号");	
				}
				else {
					alert("请至少输入一个用户组");		
				}
				return false;
			}
			var qxArr = qx.split(",");
			if(qxArr[0].length > 8) {
				if("U" == this.plType) {
					alert("工号分界有误，请使用英文输入状态的 , 分割多个工号");
				}
				else {
					alert("用户组分界有误，请使用英文输入状态的 , 分割多个用户组");		
				}
				return false;	
			}
			dancer.cansoleGh();
			for(i = 0, arrLen = qxArr.length; i < arrLen; i++) {
				data[4] = qxArr[i];	
				data[5] = qxSql;
				data[6] = '';
				clNode = this.qx_input.firstChild.cloneNode(true);
				tempTag = clNode.getElementsByTagName("*");
				valTag = this.getEle(tempTag);
				this.setData(valTag, data);
				rowNum = this.qxTable.rows.length;
				tempTr = this.qxTable.insertRow(rowNum);
				tds = clNode.getElementsByTagName("td");
				for(n = 0; n < tds.length; n++) {
					tempTd = tempTr.insertCell(n);
					tempTd.innerHTML = tds[n].innerHTML;
					if(0 == i) {
						tempTd.style.borderBottom = "1px solid #527D29";	
					}	
				}
				firstTr = this.qxTable.rows[1];
			//	this.qxTable.insertBefore(tempTr,firstTr);	
				sendData = '("'+data[0]+'","'+data[1]+'","'+data[2]+'","'+data[3]+'","'+data[4]+'","'+data[5]+'","","0","300","'+$("OID").value+'","","")';
				observer.insert("quan",rowNum, sendData);
				tempTag = tempTr.getElementsByTagName("*")
				valTag = this.getEle(tempTag);
				observer.setPuber(valTag);//绑定监听	
				dba.saveBut.style.display = "block";
			}
		},
		saveData : function() {
			var readyPublish = observer.readyPublish;
			var len = readyPublish.length;
			var sql;
			for(var i = 0; i < len; i++) {
				data = readyPublish[i].data;
				sql = data.head + " " + data.change + data.where;
			}
								//清除数据
					//observer.readyPublish.length = 0
					
		},
		checkInfoData : function(num) {
			if(0 == this.liTags[num].getElementsByTagName("table").length) {
				switch(num) {
					case 0:
						this.flwData("check");
						break;
					case 1:
						this.busData("check");
						break;	
					case 2:
						this.qxMsData("check");
						break;
					default:
						break;
				}	
			}
	
		},
		setCookie : function(name, value) {
			var days = 1;
			var exp = new Date();
			exp.setTime(exp.getTime() + days * 24 *60 * 60 * 1000);
			_doc.cookie = name + "=" + escape(value) +";expires" + exp.toGMTString();	
		},
		getCookie : function(name) {
			var arr = _doc.cookie.match(new RegExp("(^|)"+ name +"=([^;]*)(;|$)"));	
			if(null != arr) {
				return unescape(arr[2]);	
			}
			return null;
		},
		delCookie : function(name) {
			var exp = new Date();
			exp.setTime(exp.getTime() - 1);
			var cval = getCookie(name);
			if(null != cval) {
				_doc.cookie = name + "=" + cval + ";expires=" + exp.toGMTString();	
			}
		}
	}	
	var dba = new Data();
	/**show**/
	function Show(){
		this.content = $("flowFather");
		this.tipCanvas = $("tipModuel");
		///this.flwTip = $_class("new_flw_tip")[0];
		this.oprModel = $_class("opr-model", "span");
		this.stepClick = this.content.getElementsByTagName("div")[2];
		this.canvasWrap = [parseInt(this.content.getBoundingClientRect().left), parseInt(this.content.getBoundingClientRect().top)];
		this.line = {};
		this.line.start = false;//判断是否是在画线段。
		this.line.initPos = {};
		this.dotMove = false;
		this.shapList = [];
		this.shapTag = [];
		this.lineTag = {};
		this.stepConnectTip = $_class("stepConnectTip")[0];
		this.draging = false;
		this.showStepRelation = false;
		this.replaceStepId = 1000;
	}
	Show.prototype = {
		//保存按钮状态确认函数
		saveCheck : function(tag) {
			if(tag.getAttribute("type") == "checkbox"){
				if(tag.checked) {
					dba.monitoring.tag.value = 1;
				}	
				else {
					dba.monitoring.tag.value = 0;	
				}	
			}
			if(dba.monitoring.tag.value.Trim() != dba.monitoring.checkVal) {
				dba.saveBut.style.display = "block";
			}
			else {	
				if(0 == observer.readyPublish.length || (1 == observer.readyPublish.length && 1 == observer.readyPublish[0].data.tags.length && tag == observer.readyPublish[0].data.tags[0])) {
					dba.saveBut.style.display = "none";	
				}
			}
		},
		menu : function(e) {
			var pos = getMousePos(e);
			dba.menuTag.style.left = pos.x - 2 * dancer.canvasWrap[0] + "px";
			dba.menuTag.style.top = pos.y - 2 * dancer.canvasWrap[1] + "px";
			dba.menuTag.style.display = "block";
		},
		delFlwLine : function() {
			var tabTag = dba.infoRel;
			var rowLen =  tabTag.rows.length;
			var tag = tabTag.rows[rowLen - 1];
			var row = tag.rowIndex;
			if(0 == tag.rowIndex) {
				alert("暂无流转关系！");
				return false;	
			}
			else {
				tabTag.removeChild(tag);	
				dba.defaultHeight[0] -= 27; 
				dba.flwCont.style.height = dba.defaultHeight[0] + "px";
				dba.infoTag.style.height = parseInt(realStyle(dba.infoTag, "height")) - 27 + "px";
				observer.checkDel(tag, row);
			}
		},
		moveInfo : function(type) {
			var num;
			if("left" == type) {
				//判断下一个是否有内容，
				num = dba.currentLi+1;
				dba.checkInfoData(num);
				//修改当前li的高度以适应下一个切换
				this.changeHeight(num, dba.currentLi, "before");
				this.stopVal = parseInt(realStyle(dba.liMove,"left")) - 920;
				this.moveTimes = setInterval(function() {
					var initLeft = parseInt(realStyle(dba.liMove,"left"));
					if(initLeft == dancer.stopVal) {
						dba.currentLi++;
						clearInterval(dancer.moveTimes);
						dancer.setInfoDir(dba.currentLi)
						dancer.changeHeight(dba.currentLi-1, dba.currentLi-1, "after");
						dba.moveCont = false;
					}
					else {
						dba.liMove.style.left = initLeft - 40 + "px";	
					}
				}, 3);	
			}
			else if("right" == type){
				num = dba.currentLi - 1;
				dba.checkInfoData(num);
				//修改当前li的高度以适应下一个切换
				this.changeHeight(num, dba.currentLi, "before");
				this.stopVal = parseInt(realStyle(dba.liMove,"left")) + 920;
				this.moveTimes = setInterval(function() {
					var initLeft = parseInt(realStyle(dba.liMove,"left"));
					if(initLeft == dancer.stopVal) {
						dba.currentLi--;
						clearInterval(dancer.moveTimes);
						dancer.setInfoDir(dba.currentLi)
						dancer.changeHeight(dba.currentLi+1, dba.currentLi+1, "after");
						dba.moveCont = false;
					}
					else {
						dba.liMove.style.left = initLeft + 40 + "px";	
					}
				}, 3);		
			}	
		},
		setInfoDir : function(num) {
			switch(num) {
				case 0:
					dba.dirLeft.className = "info-move-left show-block";
					dba.dirRight.className = "info-move-right hide";
					break;
				case 1:
					dba.dirLeft.className = "info-move-left show-block";
					dba.dirRight.className = "info-move-right show-block";
					break;
				case 2:
					dba.dirLeft.className = "info-move-left hide";
					dba.dirRight.className = "info-move-right show-block";
					break;	
			}
		},
		changeHeight : function(num, liNum, type) {
			var tagHeight = dba.defaultHeight[num];	
			var curTag;
			switch(liNum) {
				case 0:
					curTag = dba.flwCont;
					break;
				case 1:
					curTag = dba.busCont;
					break;
				case 2:
					curTag = dba.qx_cont;
					break;
				default:
					break;
			}
			curTag.style.height = tagHeight + "px";
			if("before" == type) {
				dba.infoTag.style.height = tagHeight + 25 + "px";
			}
		},
		cansoleGh : function() {		
			dba.qx_cont.removeChild(dba.plModel);	
		},
		drawTip : function() {
			var ctx = dancer.tipCanvas.getContext('2d');
			ctx.clearRect( 0, 0, 500, 500 );
			ctx.strokeStyle = 'black';
			ctx.beginPath();
			ctx.lineWidth = 1;
			ctx.fillStyle = "#8BC54B";
			ctx.strokeStyle = 'rgb(0, 0, 100)';
			ctx.arcTo(100,10,100,20,10);
			ctx.closePath();
			ctx.stroke();	
		},
		drawStart : function() {
			var temp = {}, shap;
			var data = [{
					"text" : "开始",
					"pos1" : 600,
					"pos2" : 50
				},
				{
					"text" : "结束",
					"pos1" : 600,
					"pos2" : 500
				}];
			for(var i = 0; i <= 1; i++) {
				shap = {
					shape : 'ellipse',
					clickable : true,
					id : zr.newShapeId(),
					style : {
						x : data[i].pos1,
						y : data[i].pos2,
						a : 30,
						b : 20,
						brushType : 'both',
						color : 'rgba(162, 162, 162, 1)',// rgba supported
						text : data[i].text,
						textPosition :'inside',
						strokeColor : '#B9CAC7',
						shadowBlur : '2',
						lineWidth : '4',
						textFont:'bold 15px verdana'
					},				
					draggable : false
				};
				zr.addShape(shap);
				stepArr[shap.id] = new Array(data[i].pos1-30, data[i].pos2-20);
				stepObj[shap.id] = [1, 0];
				temp = {"type" : "ellipseo", "x1":parseInt(data[i].pos1-40+this.canvasWrap[0]), "x2":parseInt(data[i].pos1+40+this.canvasWrap[0]), "y1":parseInt(data[i].pos2-30+this.canvasWrap[1]), "y2":parseInt(data[i].pos2+30+this.canvasWrap[1]), "id":shap.id,"stepName":"结束_0", "showTip":false, "rltArr":[], "tag" : shap,"stpid":''};
				dba.stepRlt[shap.id] = temp;
				dancer.shapList.push(temp);
				dba.step[shap.id] = {};
			}
			//再绘制X和Y轴方向上的提示线。
			shap = {
				shape : 'line',
				clickable : false,
				id : "tip01",
				style : {
					xStart : 0,
					yStart : 0,
					xEnd : 0,
					yEnd : 663,
					lineWidth : 1,
					strokeColor :'rgb(83, 141, 162)',
					lineType : 'solid',
					opacity : '0'
				},	
				needArr : false,
				position :[0, 0]
			}
			zr.addShape(shap);
			shap = {
				shape : 'line',
				clickable : false,
				id : "tip02",
				style : {
					xStart : 0,
					yStart : 0,
					xEnd : 1100,
					yEnd : 0,
					lineWidth : 1,
					strokeColor :'rgb(83, 141, 162)',
					lineType : 'solid',
					opacity : '0'
				},	
				needArr : false,
				position : [0, 0]
			}
			zr.addShape(shap);
			zr.render();
			zrAdd();//添加代理事件。
		},
		drawStep : function(x, y, num, id, stepNum, stepName) {
			dancer.stepClick.className = "stepclick hide";
			stepNum = stepNum || dba.stepContinue;
			var stepName = stepName || "步骤"+"_"+ dba.stepContinue;
			var pos1 = parseInt(x);
			var pos2 = parseInt(y);
			var pos3 = pos1 + 176;
			var pos4 = pos2 + 38;

			var src, textColor, temp, type;
			if(1 == num) {
				src	= "images/nstep.png";
				textColor = '#005474';
				type = "normal";
			}
			else {
				src = "images/dstep.png";	
				textColor = '#2b9c3f';
				type = "dynamic";
			}
			var shap = {
				shape : 'image',
				id : id,
				zlevel : 2,
				imageType : "step",
				style : {
					x : 0,
					y : 0,
					image : src,
					width : 176,
					height : 38,
					color : 'rgba(135, 206, 250, 0.8)',
					text : stepName,
					textPosition :'inside',
					textFont:'bold 15px verdana',
					textColor : textColor
				},
				draggable : false,
				type : type,
				test : true,
				fiexdImage : src,
				position : [pos1, pos2],	
				onmouseup : function(params) {
					//注意：image没有事件穿透，这个地方通过upShape这个变量将image对象放到了事件穿透里面。相应的代码已放过去了。
					upShape = params.target;
				}
			}
			dba.stepIds.push(id);
			zr.addShape(shap);
			temp = {"type" : "img", "x1":pos1-10 + this.canvasWrap[0], "x2":pos3+10+this.canvasWrap[0], "y1":pos2-10+this.canvasWrap[1],  "y2":pos4+10+this.canvasWrap[1], "id":shap.id, "stepNum": stepNum,"stepName":stepName, "showTip":false, "rltArr":[],imgtype : type, "tag" : shap, "addImg":false};
			dancer.shapList.push(temp);
			dba.stepRlt[shap.id] = temp;
			stepArr[shap.id] = shap.position;
			dba.stepContinue++;
			zr.refresh();
		},
		drawStepNum : function(textId, pos, stepNum) {
			var shape = {
				shape : 'text',
				id : 'text_'+textId,
				style : {
				   x : pos[0] + 120,
				   y : pos[1]-5,
				   color : 'rgba(64, 170, 83, 0.8)',
				   lineWidth : 1,
				   text : stepNum,
				   textFont : 'normal  15px Arial',
				},
				draggable : false	
			}
			zr.addShape(shape);
			zr.refresh();
		},
/*		drawAddImg : function(addId, addStepNum) {
			var shape = {
				shape : 'image',
				id : "add_"+addId,
				imageType : "add", //图形类型
				addId : addId,
				tagStepNum : addStepNum, //添加对应的步骤号。
				style : {
					x : 0,
					y : 0,
					image : "images/add.png",
					width : 20,
					height : 20,
					textPosition :'top',
					textFont:'bold 15px verdana'
				},
				draggable : false,
				hoverPointer : 'pointer',
				clickable : true,
				position : [stepArr[addId][0] + 5, stepArr[addId][1] - 22]
			}	
			zr.addShape(shape);
			zr.refresh();
		},*/
		drawDotLine : function(start, end) {	
			var pos1  = start[0];
			var pos2  = start[1];
			var pos3 = parseInt(end[0] - start[0]);
			var pos4 = parseInt(end[1] - start[1]);
			var text, textColor;
			var shape = {
				shape : 'line',
				id : 'lineClone',
				zlevel:11,
				style : {
					xStart : 0,
					yStart : 0,
					xEnd : pos3,
					yEnd : pos4,
					lineWidth : 3,
					strokeColor :'rgba(255, 129, 0, 1)',
					lineType : 'dashed'
				},	
				draggable : false,
				needArr : true,
				position :[pos1, pos2],
				draggable : false,	
			}
			zr.addShape(shape);
			zr.refresh();
			return shape;
		},
		drawLine : function(tempTag, id) {
			var tag = tempTag || dancer.shapTag.tag;
			var style = tag.style;
			var cpX1, cpY1;
			shape = {
				shape : 'line',
				clickable : true,
				id : id || zr.newShapeId(),
				style : {
					xStart : 0,
					yStart : 0,
					xEnd : style.xEnd,
					yEnd : style.yEnd,
					startX : tag.position[0],
					startY : tag.position[1],
					endX : style.endX,
					endY : style.endY,
					lineWidth : 2,
					strokeColor :'rgb(64, 170, 83)',
					brushType : 'stroke'
				},	
				draggable : false,
				needArr : true,
				position :[tag.position[0], tag.position[1]],
				highlightStyle : {
					strokeColor : 'rgba(219, 0, 0, 1)'
				}
			}
			zr.delShape("lineClone");
			zr.addShape(shape);
			zr.refresh();
			dancer.shapeTag = '';
			return shape;
		},
		drawBrokenLine : function (points, opacity, id) {
			var id = id || zr.newShapeId();
			brokenPoints[id] = [];
			temp = [];
			for(var i=0 , l = points.length; i < l; i++) {
				brokenPoints[id][i] = [];
				temp[i] = [];
				brokenPoints[id][i] = [points[i][0], points[i][1]];	
				temp[i] =[points[i][0], points[i][1]];	
			};
			var shape = {
				shape : 'brokenLine',
				id : id,
				zlevel : brokenLevel,
				style : {
					pointList : temp,
					strokeColor : 'rgba(64, 170, 83, 1)',   // == color
					lineWidth : 4,
					brushType : 'stroke',
					opacity :opacity
				},
				draggable : false,
				needArr : true,
				highlightStyle : {
					strokeColor : 'rgba(219, 0, 0, 1)'
				},
				onmouseover : function(param) {
					shape = param.target;
				}
			};
			zr.addShape(shape);
			zr.delShape("lineClone");
			zr.refresh();
			dancer.shapeTag = '';
			return shape;
		}, 
		//修改虚线
		updateDot : function(pos) {
			pos.x = parseInt(pos.x);
			pos.y = parseInt(pos.y);
			var dotX = dancer.dotInit[0];
			var dotY = dancer.dotInit[1];
			var x = pos.x  - dancer.canvasWrap[0] - dotX;
			var y = pos.y - dancer.canvasWrap[1] - dotY + scrollTop;
			var tag = dancer.shapTag.tag;
			var id = dancer.shapTag.tag.id;
			//var shapPos = tag.position;
			//修改画布里面相对于线段起点的终点。
			zr.modShape(id, {
				style : {
					xEnd : x,
					yEnd : y	
				}	
			});
			zr.refresh();
		}
	}
	var dancer = new Show();
	/**自定义函数区域**/
	function $(id) {
		return _doc.getElementById(id);	
	}
	function $_class(name, ele, parent) {
		var tag = ele || "*";
		var parentNode = parent || _doc;
		var allTags = parentNode.getElementsByTagName(tag);
		var tagNums = allTags.length;
		var element = [];
		var i=0;
		for(var i = 0, _len = allTags.length; i < _len; i++){
			current = allTags[i];
			if(current!=null && undefined != current.className) {
				if(current.className==name || 0 <= current.className.indexOf(name)){
					element.push(current);
				}
			}
		}
		return element;	
	}
	function getEventTag(e) {
  		e = e || window.event;
  		return e.target || e.srcElement;
	}
	function ce(tag) {
		return  _doc.createElement(tag);
	}
	function ge(name) {
		return getElementsByTagName(name);
	}
	function ceDfg() {
		return _doc.createDocumentFragment();	
	}
	function getPos(tag) {
		var ua = navigator.userAgent.toLowerCase();
		var isOpera = (ua.indexOf('opera') != -1);
		var isIE = (ua.indexOf('msie') != -1 && !isOpera); // not opera spoof 
		if (tag.parentNode === null || tag.style.display == 'none') {
			return false;
		}
		var parent = null;
		var pos = [];
		var box;
		if (tag.getBoundingClientRect)  
		{
			box = tag.getBoundingClientRect();
			var scrollTop = Math.max(_doc.documentElement.scrollTop, _body.scrollTop);
			var scrollLeft = Math.max(_doc.documentElement.scrollLeft, _body.scrollLeft);
			pos[0] = box.left + scrollLeft + "px";
			pos[1] = box.bottom +scrollTop + "px";
			return pos;
		}
	}
	function getMousePos(event) {
		/*ie 与 ff的边界 处理不同*/
		if (ie) {
			mousePos = {
				x: event.clientX,
				y: event.clientY
			}
		}
		else {
			mousePos = {
				x:event.clientX+_body.scrollLeft+_doc.documentElement.scrollLeft,
				y:event.clientY+_body.scrollTop+_doc.documentElement.scrollTop
			}
		}
		return mousePos;
	}
	function inArray(arr, ele) {
		for(var i in arr) {
			if(arr[i] == ele) {
				return true;	
			}	
		}
		return false;
	}
	/**
	*	获取当前节点的前一个节点，排除Mozilla 里面的文本节点。	
	*/
	function getPrevioussibling(n){
		var x=n.previousSibling;
		while (x.nodeType!=1){
			x=x.previousSibling;
			}
		return x;
	}
	function getNextSibling(n) {
		var x=n.nextSibling;
		while (x.nodeType!=1){
			x=x.nextSibling;
		}
		return x;
	}
	/**
	 *对象深度克隆
	*/
	function deepClone(obj){
		var newobj, s;
		if(typeof obj !== 'object'){
		  return;
		}
		newobj = obj.constructor === Object ? {} : [];
		if(window.JSON){
			s = JSON.stringify(obj), //系列化对象
			newobj = JSON.parse(s); //反系列化（还原）
		}else{
			if(newobj.constructor === Array){
				newobj.concat(obj);
			}else{
				for(var i in obj){
					newobj[i] = obj[i];
				}
			}
		}
		return newobj;
	}
	//ajax代码
	function request(url, opt) {
		(function fn() {
			var async = opt.async !== false,
				method = opt.method || 'GET',
				data = opt.data || null,
				success = opt.success || fn,
				failure = opt.failure || fn,
				method = method.toUpperCase();
			if(method == 'GET' && data) {
				url += (url.indexOf('?') == -1?'?':'&') + data;
				data = null;	
			}		
			var xhr = window.XMLHttpRequest? new XMLHttpRequest():new ActiveXobject('Microsoft.XMLHTTP');
			xhr.open(method, url, async);
			if('POST' == method) {
				xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencode;');	
			}
			xhr.onreadystatechange = function() {
				_onStateChange(xhr, success, failure);	
			};
			xhr.send(data);
			return xhr;	
		})();
		
		function _onStateChange(xhr, success, failure) {
			switch(xhr.readyState) {
				case 1:
					break;
				case 2:
					break;
				case 3:
					break;
				case 4:
					if(xhr.status >= 200 && xhr.status <300 ) {
						success(xhr.responseText);	
						xhr.abort;
					}
					else {
						failure(xhr);	
					}	
				break;
				default:
					break;
			}
		}
	}
	function realStyle(tag, styleName) {
		var realStyle;
		if (tag.currentStyle) {
			realStyle = tag.currentStyle[styleName];
		}
		else if (window.getComputedStyle) {
			realStyle = window.getComputedStyle(tag,null)[styleName];
		}
		return realStyle;	
	}
	function tableTag (tag) {
		if(ie) {
			return tag.firstChild;
		}
		else {
			return tag.childNodes[1];	
		}
	}
	/**
	 *表单用户点击相应函数，主要用于判断用户是否更改数据。以控制保存按钮显示。
	 *@param {object} tag 当前操作的表单对象
	*/
	function formRespond(tag) {
		if(dba.monitoring.monitor) {
			clearInterval(dba.monitoring.monitor);
		}
		var field = tag.getAttribute("field");
		switch(field) {
			case "time":
				WdatePicker();
				break;
			default:
				break;
		}
		dba.monitoring.checked = false;	
		dba.monitoring.changed = dba.monitoring.changed ? dba.monitoring.changed : [];
		for(var i  = 0, input; input = dba.monitoring.changed[i++];) {
			if(input.obj == tag) {
				dba.monitoring.checkVal = input.val;
				dba.monitoring.checked = true;	
			}	
		}
		if(!dba.monitoring.checked) {
			if(tag.getAttribute("type") == "checkbox") {
				if(tag.checked) {
					dba.monitoring.checkVal = 0;
				}	
				else {
					dba.monitoring.checkVal = 1;	
				}
			}
			else {
				dba.monitoring.checkVal = tag.value.Trim();	
			}
			dba.monitoring.changed.push({obj:tag, val:dba.monitoring.checkVal});
		}
		dba.monitoring.tag = tag;
		dba.monitoring.monitor = setInterval(
			(function(tag){
				 return function(){
					 dancer.saveCheck(tag);
				}
			})(tag),250);			
		if(tag.getAttribute("type") == "checkbox") {
			observer.monitoring(tag);	
		}
	}
	//准备拖动
	function moveDefault() {
		dba.canMove = true;
		var mouseStart = [dba.mousePos.x, dba.mousePos.y] ;
		dba.moveTag.startLeft = mouseStart[0] - parseInt(realStyle(dba.moveTag, "left"));
		dba.moveTag.startTop = mouseStart[1] - parseInt(realStyle(dba.moveTag, "top"));	
	}
	function zrAdd() {
		var config = require('zrender/config');
		var oprateTag, type, shape, event;   //oprateTag用来存储down时的操作对象，避免在UP的时候触发另外一个对象。
		var x, y, brokenPoint = [];
		var startRlt, endRlt, line, newRlt;
		var startNum, endNum;
		zr.on(config.EVENT.MOUSEOVER, _eventHandler);
		zr.on(config.EVENT.MOUSEOUT, _eventHandler);
		zr.on(config.EVENT.MOUSEDOWN, _eventHandler);
		zr.on(config.EVENT.MOUSEUP, _eventHandler);
		zr.on(config.EVENT.DRAGSTART, _eventHandler);
		zr.on(config.EVENT.DRAGEND, _eventHandler);
		zr.on(config.EVENT.DRAGENTER, _eventHandler);
		zr.on(config.EVENT.DRAGOVER, _eventHandler);
		zr.on(config.EVENT.DRAGLEAVE, _eventHandler);
		zr.on(config.EVENT.DROP, _eventHandler);
		function _eventHandler(params) {
		 	type = params.type;
			shape = params.target;
			event = params.event;
			switch(type) {
				case "dragstart":
					switch(shape.shape) {
						case "image":
							moved = true;
							var replaceShape = {
								shape : 'image',
								id : dancer.replaceStepId,
								style : {
									x : 0, y : 0, image :shape.style.image, width: 176,
									height: 38,color : 'rgba(135, 206, 250, 0.8)',
									text : shape.style.text, opacity: 0.5,
									textPosition :'inside',
									textFont:'bold 15px verdana',
									textColor : shape.style.textColor	
								},
								position : [shape.position[0], shape.position[1]]	
							}
							zr.addShape(replaceShape);
							zr.modShape(shape.id, {
								style : {image:"images/move.png"}	
							});
							zr.refresh();
							if(2 <= clickArr.length && undefined != clickArr[shape.id]) {
								upShape = params.target;
								groupMove = true;	
							}
							break;
						case "circle":	
							if("tipPoint01" == shape.id || "tipPoint02" == shape.id) {
								dancer.linePortMoving = true;
								goFlow.judge.lineDrag = true;
							}
							break;
						}
						break;
				case "dragend":
					switch(shape.shape) {
						case "image":
							zr.delShape(dancer.replaceStepId);
							zr.modShape(shape.id, {
								style : {image:shape.fiexdImage}	
							});
							zr.refresh();
							moved = false;
							if(10 < Math.abs(shape.position[0] - stepArr[shape.id][0]) || 10 < Math.abs(shape.position[1] - stepArr[shape.id][1])) {
								upStepPos(shape.id, shape.position[0], shape.position[1]);
							}
							else if(shape.position[0] != stepArr[shape.id][0] || shape.position[1] != stepArr[shape.id][1]) {
								zr.modShape(shape.id, {position: stepArr[shape.id]})
							}
							zr.refresh();
							break;
						case "circle" :
							if(shape.id >= 8000) {
								zr.delShape("lineClone");
								tempArr = noRepeatPoint(brokenPoint);
								brokenPoints[shape.shapeId] = tempArr;
								brokenPoint = tempArr;
								zr.delShape(shape.shapeId);
								dancer.drawBrokenLine(tempArr, shape.style.opacity, shape.shapeId);
								zr.refresh();
							}
							else {
								dancer.linePortMoving = false;
								goFlow.judge.lineDrag = false;
								if(!lineStartJudge.adjust) {
									return false;
								}
								else {
									line = dba.lineRlt[shape.shapeId];
									startRlt = dba.stepRlt[line.startStep].rltArr;
									endRlt = dba.stepRlt[line.endStep].rltArr;
									//找到旧开始关系数据,需考虑一个步骤与另一个步骤有多个关系的情况
									for(i = 0, len = startRlt.length; i < len;i++) {
										if("start" == startRlt[i].type
										 	&& line.endStep ==  startRlt[i].tagId[1]
										 	&& line.tag == startRlt[i].lineTag) {
											startNum = i;
											break;
										}	
									}
									startRlt = startRlt[i];

									for(i = 0, len = endRlt.length; i < len; i++) {
										if("end" == endRlt[i].type && line.startStep == startRlt.tagId[0]) {
											//startRlt.tagId[0] = lineStartJudge.stepId;
											endNum = i;
											break;	
										}	
									}
									endRlt = endRlt[i]
									if("tipPoint01" == shape.id) {
										if(lineStartJudge.stepId == line.startStep) {
											if(lineStartJudge.direction == startRlt.startPoint) {
												return false;	
											}
											else {
												startRlt.startPoint = lineStartJudge.direction;
												endRlt.startPoint = lineStartJudge.direction;
											}
										}
										else {
											//新开始添加
											dba.stepRlt[lineStartJudge.stepId].rltArr.push({
												"type" : "start",
												"flwType" : startRlt.flwType,
												"startPoint" : lineStartJudge.direction,
												"endPoint" : startRlt.endPoint,
												"lineTag" : startRlt.lineTag,
												"tagId" : [lineStartJudge.stepId, startRlt.tagId[1]] 
											});
											//删除旧开始
											dba.stepRlt[line.startStep].rltArr.splice(startNum, 0);
											//修改结束
											endRlt.startPoint = lineStartJudge.direction;
											endRlt.tagId[0] = lineStartJudge.stepId;
										}
										//修改连续属性
										line.startStep = lineStartJudge.stepId;
										line.startDir = lineStartJudge.direction;
										line.x1 = lineStartJudge.pos[0];
										line.y1 = lineStartJudge.pos[1];	
									}
									else {
										if(lineStartJudge.stepId == line.endStep) {
											if(lineStartJudge.direction == endRlt.endPoint) {
												return false;	
											}
											else {
												startRlt.endPoint = lineStartJudge.direction;
												endRlt.endPoint = lineStartJudge.direction;	
											}
										}
										else {
											//新结束添加
											dba.stepRlt[lineStartJudge.stepId].rltArr.push({
												"type" : "end",
												"flwType" : endRlt.flwType,
												"startPoint" : endRlt.startPoint,
												"endPoint" : lineStartJudge.direction,
												"lineTag" : endRlt.lineTag,
												"tagId" : [endRlt.tagId[0], lineStartJudge.stepId]
											})	
											//删除旧结束
											dba.stepRlt[line.endStep].rltArr.splice(endNum, 0);
											//修改开始
											startRlt.endPoint = lineStartJudge.direction;
											startRlt.tagId[1] = lineStartJudge.stepId;
										}
										line.endStep = lineStartJudge.stepId;
										line.endDir = lineStartJudge.direction;
										line.x2 = lineStartJudge.pos[0];
										line.y2 = lineStartJudge.pos[1];
									}
									delStepBorder();	
									//重绘线
									upRltLine([line.startStep]);
								}

							}
							clearClicked();
							break;
					}
					break;
				case "mousedown":
					var shapeA;
					if(shape) {
						oprateTag = shape;
						if("tipPoint01" == shape.id || "tipPoint02" == shape.id) {
							zr.delShape("lineClone")
							brokenPoint = brokenPoints[shape.shapeId]
							dancer.lineTag = dancer.drawDotLine(brokenPoint[0],brokenPoint[brokenPoint.length-1]);
						}
					}	
					else {
/*						x = zrEvent.getX(event);
						y = zrEvent.getY(event);
						shapeA = {
							shape : 'rectangle',
							id : 'choiceRec',
							style : { 
								 x : x,
								 y : y,
								 width : 0,
								 height : 0,
								 brushType : 'both',
								 color : '#BBDDF7',
								 opacity : '0.3',
								 lineWidth : 2,
								 strokeColor : '#124F85'
							},
							needCover : true,
						}
						choiceRecInfo.tag = shapeA;
						choiceRecInfo.start = [x, y];
						choiceRecInfo.draw = true;
						goFlow.judge.choiceMoving = true;*/
					}
					break;
				case "mousemove":
					if(choiceRecInfo.draw) {
						x = zrEvent.getX(event);
						y = zrEvent.getY(event);
						width = x - choiceRecInfo.start[0];
						height = y - choiceRecInfo.start[1];
/*						zr.modShape("choiceRec", {
							style : {
								width : width,
								height : height	
							}	
						})
						zr.refresh();*/
					}
					break;
				case "mouseover" : 
					if(undefined != shape.imageType) {
						switch(shape.imageType) {
							case "add":
								zr.modShape(shape.id, {
									style : {text:"添加分支条件"}	
								});
								break;
							case "step":	
								if(dancer.showStepRelation) {
									zr.modShape(params.target.id, {
										style : {image:"images/eye.png"},	
										draggable:false	
									});
								}
								else {
									zr.modShape(params.target.id, {
										draggable:true
									})	
								}
								break;
						}
						zr.refresh();	
					}
					break;
				case "mouseout" :
					if(shape) {
						if("tipPoint01" == shape.id || "tipPoint02" == shape.id) {
							zr.modShape(shape.id, {
								style : {
									textColor:'rgba(255, 69, 0, 1)'	
								}	
							})
							zr.refresh();
						}
						if(undefined != shape.imageType) {
							switch(shape.imageType) {
								case "add":
									zr.modShape(shape.id, {
										style : {text:""}	
									});
									break;
								case "step":	
									if(dancer.showStepRelation) {
										zr.modShape(params.target.id, {
											style : {image:params.target.fiexdImage},	
											draggable:false	
										});
									}
									else {
										zr.modShape(params.target.id, {
											draggable:true
										})	
									}
									break;
							}
							zr.refresh();	
						}
					}
					break;
				case "mouseup":
					var src;
					var x1, y1, x2, y2;
					var text, src, id;
					var left = dancer.canvasWrap[0];
					var top = dancer.canvasWrap[1];
					shape = upShape ||params.target;//对于shape的赋值，优先考虑upShape.
					var points = [], len;//折线的拐点。
					var passMiddlePoints = [], passInflexionPoints = [];//传给绘制中点和拐点的方法的点集合，一次性刷新。
					var a, b;//取中间点的时候判断是否有3个连线点在同一条直线上。用a , b表示线段的开始和结束点。
					var pointAssistant = [];//中点助理，记录中点所在线段的起点和终点坐标，已经根据坐标确定其移动的方向。
					var tempAss = {};
					var mouseBut = event.button;
					//优先处理框选动作。
					if(choiceRecInfo.draw) {
						if(0 != clickArr.length) {
							clearClicked();//先清除已有效果。
						}	
						event = params.event;
						x = zrEvent.getX(event);
						y = zrEvent.getY(event);
						//框选对象获取
						if(x > choiceRecInfo.start[0]) {
							x1 = choiceRecInfo.start[0] - 10 + left;
							x2 = x + 10 + left;
						}
						else {
							x1 = x  - 10 + left;
							x2 = choiceRecInfo.start[0] + 10 + left;	
						}
						
						if(y >  choiceRecInfo.start[1]) {
							y1 = choiceRecInfo.start[1] - 10 + top;
							y2 = y + 10 + top;
						}
						else {
							y1 = y - 10 + top;
							y2 = choiceRecInfo.start[1] + 10 + top;	
						}
						//findRecChoice(x1, x2, y1, y2);
					//	zr.delShape("choiceRec");
						zr.refresh();
						choiceRecInfo.draw  = false;	
						goFlow.judge.choiceMoving = false;
						return;
					}
					if(shape != oprateTag) {
						oprateTag = '';
						return false;	
					}
					if(shape) {
						switch(shape.shape) {
							case "line" :
								if(0 != clickArr.length) {
									clearClicked();//先清除已有效果。
								}
								 //先修改颜色表示click的对象，
								 zr.modShape(shape.id, {
									style: {
										strokeColor :'rgb(255, 129, 0)',
									},
									draggable : false
								});
								//然后再画两个表示线段开始和结束的园
								lineTag = {};
								lineTag.id = shape.id;
								lineTag.style = shape.style;
								lineTag.position = shape.position;
								dancer.lineTag = lineTag;
								addLinePoint(lineTag.position[0]+lineTag.style.xStart, lineTag.position[1]+lineTag.style.yStart, lineTag.position[0] + lineTag.style.xEnd, lineTag.position[1] + lineTag.style.yEnd);
								zr.refresh();
								break;
							case "image" : 
								clearClicked();
								id = shape.id;
								if(0 == mouseBut) {   //左键
									if(dancer.showStepRelation) {  //由于层叠的关系，关系连线可能显示不完全，这里在一个新层上重新绘制.
										if(8000 != dba.eyaBrokenPointsId) {
											while(dba.eyaBrokenPointsId >= 8000) {
												zr.delShape(dba.eyaBrokenPointsId--);	
											}
											dba.eyaBrokenPointsId = 8000;
										}
										rlt = dba.stepRlt[id].rltArr
										for(var i=0, rltLen = rlt.length; i<rltLen;i++) {
											if("start" == rlt[i].type) {
												 shape = {
													shape : 'brokenLine',
													id : dba.eyaBrokenPointsId,
													zlevel : 10,
													style : {
														pointList : brokenPoints[rlt[i].lineTag.id],
														strokeColor : 'rgba(255, 0, 0, 1)',   // == color
														lineWidth : 4,
														brushType : 'stroke',
														text: rlt[i].flwType,
														textPosition: 'end',
														textFont : 'bold 20px verdana'
													},
													needArr : true
												};
												zr.addShape(shape);
												dba.eyaBrokenPointsId++;
											}
										}
										zr.refresh();
										break;	
									}
									if(stepClick.judge && (stepClick.lastTag == shape || 1000 == shape.id)) {
											text = shape.style.text;
											changeNameId = id;
											zr.modShape(changeNameId,{
												style : {
													text : ''	
												}	
											});
											zr.refresh();
											showStepInput(text, shape.position[0], shape.position[1]);
											clearTimeout(stepClick.lastTime);	
											stepClick.lastTag = '';
											stepClick.judge = false;
									}
									else {
										stepClick.lastTag = shape;
										stepClick.judge = true; 
										stepClick.lastTime = setTimeout(function(){
											stepClick.lastTag = '';
											stepClick.judge = false;
										}, 300);	
									} 	
									//修改dancer.shapeList里面的x1,x2,y1,y2的值。
									//_groupUpdateList(id);
									
									if(!moved) {
/*										if("dynamic" == shape.type) {
											src = "images/dcstep.png";
										}
										else {
											src = "images/ncstep.png";	
										}
										zr.modShape(id, {
											style : {
												image : src	
											}	
										});*/
									//	zr.refresh();
										//clickArr.push(dancer.shapList[id - 1]);
										clickArr.push(dba.stepRlt[id])
									}
									else {
										moved = false;	
									}
								}
								else {
									if(2 == mouseBut) {  //右键
										dba.currStep = id;
										menuShow = "open";
									}
								}
								upShape = '';
								break;
							case "brokenLine":
								if(undefined == dancer.lineTag || dancer.lineTag.id != shape.id) {
									points = brokenPoints[shape.id];
									len = points.length;
									zr.addShape({
										shape : 'brokenLine',
										id : "lineClone",
										zlevel : 11,
										style : {
											pointList : points,
											strokeColor : 'rgba(255, 129, 0, 1)',   
											lineWidth : 2,
											lineCap : 'round',
       										lineType : 'dashed',
											lineJoin : 'miter',
											miterLimit : 50
										},
										draggable : false,
										needArr : true
									});
									//先把开始点和结束点拖动点添加进来。
									addLinePoint(points[0][0], points[0][1], points[len - 1][0], points[len - 1][1], shape.id);
									//判断是不是直线，如果是直线的话直接处理否则进行逻辑运算
									if(4 == len) {
										if(points[0][0] == points[len - 1][0]) {
											tempAss.cursor = "e-resize";
											tempAss.dir = "left-right";
											passMiddlePoints.push([points[0][0], points[0][1] + (points[len-1][1] - points[0][1])/2]);
										}
										else {
											tempAss.cursor = "n-resize";
											tempAss.dir = "up-down";
											passMiddlePoints.push([points[0][0] + (points[len-1][0] - points[0][0])/2, points[len-1][1]]);		
										}	
										tempAss.last = 0;
										tempAss.next = 1;	
										pointAssistant.push(tempAss);
									}
									else {
										for(var i = 1; i < len - 2; i++) {		
											a = points[i];
											b = points[i+1];
											tempAss = {
												"last" : i,
												"next" : i + 1
											}
											//求出中点坐标.
											if(a[0] == b[0]) {
												tempAss.cursor = "e-resize";
												tempAss.dir = "left-right";
												if(i == 1) {
													if(points[2][0] == b[0]) { 
														b = points[i+2];
														tempAss.last = 1;
														tempAss.next = 2;
													}
												}
												if((len-3) == i && points[len-1][0] == b[0]) {
													b = points[len-1];
													tempAss.last = len - 3;
													tempAss.next = len - 2;	
												}
												passMiddlePoints.push([a[0], a[1] + (b[1] - a[1])/2]);	
												pointAssistant.push(tempAss);
											}
											else {
												tempAss.cursor = "n-resize";
												tempAss.dir = "up-down";
												if(i == 1){
													if(points[3][1] == b[1]) { 
														b = points[i+2];
														tempAss.last = 1;
														tempAss.next = 2;
														i++;
													}
												}
												if((len-3) == i && points[len-3][1] == points[len-1][1]) {
													b = points[len-1];
													tempAss.last = len - 3;
													tempAss.next = len - 2;	
												}
												passMiddlePoints.push([a[0] + ( b[0] - a[0])/2, b[1]]);	
												pointAssistant.push(tempAss);
											}
										}
										//添加拐点。
										passInflexionPoints.push(points[i]);	
									}
									if(0 != clickArr.length) {
										clearClicked();//先清除已有效果。
									}
									clickArr.push(dba.lineRlt[shape.id]);
									dba.brokenId = _onLinePoint(passMiddlePoints, pointAssistant, shape.id);
									lineTag = {};
									lineTag.id = shape.id;
									lineTag.style = shape.style;
									dancer.lineTag = lineTag;
								}
								break;
							default :
								clearClicked();
								break; 	
						}	
						return;	
					}
					break;
			}
			//群体移动结束后修改list里面的关系。
			function _groupUpdateList(id) {
				var clickedNum = clickArr.length, clickTag;
				for(var i = 0; i <= clickedNum; i++) {
					clickTag = clickArr[i];
					if(undefined == clickTag || id == clickTag.id) {
						continue;	
					}
					else {	
						clickTag.x1 += totalDx;
						clickTag.y1 += totalDy;
						clickTag.x2 += totalDx;
						clickTag.y2 += totalDy;
					}
				}	
				totalDx = totalDy = 0;
			}	
			/**
			 *添加折线上两个拐点间的移动点，并指定每个点的移动方向。
			 *@param {array} points 当前折线的折点数组
			 *@param {array} assistan 每个移动点的鼠标方向键和这个点移动时修改的折线上的点
			 *@param {string} shapeId 折线的ID
			*/ 
			function _onLinePoint(points, assistant, shapeId) {
				var id = 8000, j;
				var len = points.length;
				for(var i = 0; i < len; i++) {
					j = i ;
					shape = {
						shape : 'circle',
						id : id,
						style : {
							x: points[i][0], y: points[i][1], r: 3,
							brushType : 'both',
							color : 'rgb(255, 69, 0)'// rgba supported
						},
						zlevel:12,
						last : assistant[j].last,
						cursor : assistant[j].cursor,	
						next : assistant[j].next,		
						dir : assistant[j].dir,
						shapeId : shapeId,
						draggable : true,
						ondragstart: function(){
							this.brokenPoint = [];
							var source =  brokenPoints[shapeId];
							for(var i = 0, len = source.length; i < len; i++) {
								this.brokenPoint[i] = [];
								this.brokenPoint[i] = [source[i][0], source[i][1]];	
							}
						},
						ondrift : function(shape, dx, dy) {
							var pointA = shape.last;
							var pointB = shape.next;
							brokenPoint = this.brokenPoint;
							var len = brokenPoint.length;
							var lastThird = len - 3;
							var lastSecond = len - 2;
							var lastOne = len - 1; 
							_pointJudge();
							brokenPoint[pointA][0] = brokenPoint[pointA][0] + dx;
							brokenPoint[pointA][1] = brokenPoint[pointA][1] + dy;
							brokenPoint[pointB][0] = brokenPoint[pointB][0] + dx;
							brokenPoint[pointB][1] = brokenPoint[pointB][1] + dy;
							this.brokenPoint = brokenPoint;
							zr.modShape("lineClone", {
								style : {
									pointList : brokenPoint	
								}	
							});
							zr.refresh();
							//新增或者删除节点判断。
							function _pointJudge() {
								if(0 == pointA) {
									if(brokenPoint[0][0] == brokenPoint[1][0]) {
										if((brokenPoint[1][0]+dx > brokenPoint[1][0] && brokenPoint[1][0]+dx > brokenPoint[0][0])
											|| (brokenPoint[1][0]+dx < brokenPoint[1][0] && brokenPoint[1][0]+dx < brokenPoint[0][0])){
											brokenPoint.splice(2, 0, [brokenPoint[1][0], brokenPoint[1][1]]);
											brokenPoint.splice(3, 0, [brokenPoint[3][0], brokenPoint[3][1]]);
											pointA = 2;
											pointB = 3;
											zr.modShape(shape.id, {
												last:2,
												next:3	
											})
											zr.refresh();
										}	
									}
									else if((brokenPoint[1][1]+dy > brokenPoint[1][1] && brokenPoint[1][1]+dy > brokenPoint[0][1])
											|| (brokenPoint[1][1]+dy < brokenPoint[1][1] && brokenPoint[1][1]+dy < brokenPoint[0][1])){
										brokenPoint.splice(2, 0, [brokenPoint[1][0], brokenPoint[1][1]]);
										brokenPoint.splice(3, 0, [brokenPoint[3][0], brokenPoint[3][1]]);
										pointA = pointA + 1;
										pointB = pointB + 1;
										zr.modShape(shape.id, {
											last:2,
											next:3	
										})
										zr.refresh();
									}
									return;
								}	
								if(1 == pointA) {
									if(dy != 0) {
										if((brokenPoint[1][1]+dy > brokenPoint[1][1] && brokenPoint[1][1]+dy > brokenPoint[0][1])
												|| (brokenPoint[1][1]+dy < brokenPoint[1][1] && brokenPoint[1][1]+dy < brokenPoint[0][1])){
											brokenPoint.splice(2, 0, [brokenPoint[1][0], brokenPoint[1][1]]);
											pointA = pointA + 1;
											pointB = pointB + 1;
											zr.modShape(shape.id, {
												last:pointA,
												next:pointB	
											})
											zr.refresh();
										}
									}
									else {
										if(brokenPoint[lastSecond][0] + dx > brokenPoint[lastSecond][0] && brokenPoint[lastSecond][0] + dx > brokenPoint[lastOne][0]
										||brokenPoint[lastSecond][0] + dx < brokenPoint[lastSecond][0] && brokenPoint[lastSecond][0] + dx < brokenPoint[lastOne][0]) {
											brokenPoint.splice(2, 0, [brokenPoint[1][0], brokenPoint[1][1]]);
											pointA = pointA + 1;
											pointB = pointB + 1;
											zr.modShape(shape.id, {
												last:pointA,
												next:pointB	
											})
											zr.refresh();
										}
									}
									return;
								}
								if(lastOne == pointB) {
									pointB = pointB - 1;
									zr.modShape(shape.id, {
										next :	pointB
									});
									zr.refresh();
									return;
								}
								if(lastSecond == pointB) {
									if(dy != 0) {
										if(brokenPoint[lastSecond][1] + dy > brokenPoint[lastSecond][1] && brokenPoint[lastSecond][1] + dy > brokenPoint[lastOne][1]
										||brokenPoint[lastSecond][1] + dy < brokenPoint[lastSecond][1] && brokenPoint[lastSecond][1] + dy < brokenPoint[lastOne][1]) {					
											brokenPoint.splice(lastSecond, 0, [brokenPoint[lastSecond][0], brokenPoint[lastSecond][1]]);
										}
									}
									else {
										if(brokenPoint[lastSecond][0] + dx > brokenPoint[lastSecond][0] && brokenPoint[lastSecond][0] + dx > brokenPoint[lastOne][0]
										||brokenPoint[lastSecond][0] + dx < brokenPoint[lastSecond][0] && brokenPoint[lastSecond][0] + dx < brokenPoint[lastOne][0]) {
											brokenPoint.splice(lastSecond, 0, [brokenPoint[lastSecond][0], brokenPoint[lastSecond][1]]);
										}
									}
									return;
								}	
							}	
						}
					}
					zr.addShape(shape);
					id++;
				}
				zr.modShape(shapeId, {
					style: {
						strokeColor :'rgba(255, 129, 0, 0.3)'
					}
				});
				zr.refresh();
				return id;
			}
		}
		//var lineTag = {};
		/**
		 *添加图片点击后，根据步骤的N关系显示添加分支SQL的DIF
		 @param {string} stepId   步骤图形ID
		*/
/*		function _showNRelDiv(stepId, stepNum) {
			var rlt = dba.stepDel[stepNum];  
			var innerHtml = '';
			var sec = $("stepRelSec");
			//先修改title 流转关系分支条件
			$_class("step-relation-title", "div")[0].innerHTML = "流转关系分支条件：" + dba.stepRlt[stepId].stepName ;
			for(var i = 0, j = 1, len = rlt.length; i < len; i++) {
				if("N" == rlt[i][3] || "A" == rlt[i][3]) {
					innerHtml = innerHtml +"<input id='label-"+j+"' class='label-input' type='radio' name='lida' /><label id='item_"+j+"' class='step-relation-label' for='label-"+j+"'><i></i>步骤_"+rlt[i][6]+"</label>";
				if(1 == j) {
						innerHtml = innerHtml + "<div class='show-block'>";			
					}
					else {
						innerHtml = innerHtml + "<div class='hide'>";	
					}
					j++;
				}	
				innerHtml = innerHtml + "关系名称：<input type='text' class='relation-name' id='rltName_"+i+"' /><textarea class='relation-sql' id='rltsql_"+i+"'></textarea><a>更多定制</a></div>"
			}
			$("stepRelSec").innerHTML = innerHtml;
			dba.sqlRelationDiv.className = "step-relation";
		}*/
	}
	/***********各类提示图形方法区***********/
	/**
	 *添加线段提示。
	*/
	function addLinePoint(x1,y1,x2,y2,shapeId) {
		var shape = {
			shape : 'circle',
			id : 'tipPoint01',
			style : {
				x: x1, y: y1, r: 4,
				color : 'rgba(255, 69, 0, 1)'// rgba supported
			},	
			highlightStyle : {
				r : 8,
				strokeColor : 'rgba(219, 0, 0, 1)'
			},
			zlevel:13,		
			shapeId : shapeId,
			draggable : true,
			movePointer : '',
			ondrift : function(shape, dx, dy) {
				var tag = dancer.lineTag;
				zr.modShape("lineClone",{
					style :{
						xStart : tag.style.xStart + dx,
						yStart : tag.style.yStart + dy,
						startX : tag.style.startX + dx,
						startY : tag.style.startY + dy,
					}
				});
				zr.refresh();
			},
			ondragend : function() {
	
			}			
		};
		zr.addShape(shape); 
		shape = {
			shape : 'circle',
			id : 'tipPoint02',
			zlevel:13,
			shapeId : shapeId,
			style : {
				x: x2, y: y2, r: 4,
				brushType : 'both',
				color : 'rgba(255, 69, 0, 1)'// rgba supported
			},	
			highlightStyle : {
				r : 8,
				strokeColor : 'rgba(219, 0, 0, 1)'
			},			
			draggable : true,
			movePointer : '',
			ondrift : function(shape, dx, dy) {
				dx = parseInt(dx);
				dy = parseInt(dy);
				var tag = dancer.lineTag;
				tag.style.xEnd += dx;
				tag.style.yEnd += dy;			
				zr.modShape("lineClone",{
					style :{
						xEnd : tag.style.xEnd, 
						yEnd : tag.style.yEnd
					}
				})
				zr.refresh();
			},
			ondragend : function(param) {

			}			
		};
		zr.addShape(shape); 
		zr.refresh();
	}
	
	//清除图形点击效果
	function clearClicked() {
		var ids = dba.brokenId;
		var clickedNum = clickArr.length;
		if(0 != clickedNum) {
			for(var i = 0; i < clickedNum; i++) {
			 	clickTag = clickArr[i];
				if(undefined == clickTag) {
					continue;	
				}			
				switch(clickTag.type) {
					case "line" :	
						zr.modShape(clickTag.id ,{
							style : {
								strokeColor :'rgb(64, 170, 83)'
							}
						});
						zr.delShape("tipPoint01");
						zr.delShape("tipPoint02");	
						zr.refresh();	
						break;
					case "img":
						if("normal" == clickTag.imgtype) {
							src = "images/nstep.png";
						}
						else {
							src = "images/dstep.png";	
						}
						zr.modShape(clickTag.id ,{
							style : {
								image : src								
							}	
						});	
						zr.refresh();
						break;
					case "brokenLine":
						if(undefined != ids) {
							for(var j = ids; j >= 8000; j--) {
								zr.delShape(j);	
							}	
							zr.delShape("tipPoint01");
							zr.delShape("tipPoint02");
							zr.delShape("lineClone");
						}
						zr.modShape(clickTag.id ,{
							style : {
								strokeColor : 'rgb(64, 170, 83)'
							}
						});
						zr.refresh();
						break;
					case "ellipseo":
						zr.modShape(clickTag.id, {
							style : {
								textColor : 'rgb(255, 255, 255)'	
							}	
						});
						zr.refresh();
						break;
				}	
			}
			dancer.lineTag = '';
			clickArr.length = 0;	
		}	
	}

	/**********线上提示点结束*************/
	/*************************************/
	//销毁掉线段的注释。
	function destroyLineTip() {

	}
	//移动中比较不同的图形类型点是否有重叠
	function lineMovingOver(x, y) {
		var overTag;
		y = y + scrollTop;
		var stepList = dba.stepRlt;
		for(var i in stepList) {
			shape = stepList[i]
			if((shape.x1 <= x && shape.x2 >= x) && (shape.y1 <= y && shape.y2 >= y)) {
				//开始画步骤提示小圆圈。
				lineStartJudge.stepId = shape.id;
				drawStepBorder(shape.type, [shape.x1+10-dancer.canvasWrap[0], shape.y1 + 10 - dancer.canvasWrap[1]]);
				shape.showTip = true;
			}
			else if(shape.showTip) {
				delStepBorder();	
				shape.showTip = false;
				lineStartJudge.stepId = '';
			}
		}	
	}
	//画图按钮之间的切换,解决图标工具间不停点击所代码的问题。
	function drawSwitch(num) {
		var id;
		switch(num) {
			case 0:
				return false;
				break;
			case 1:
			case 2:		
				dancer.stepClick.className = "stepclick hide";
				dba.canMove = false;
				dba.moveTag = "";
				break;
			case 3:
			case 4:
			case 5:
				if(dancer.dotMove) {
					zr.delShape("lineClone");
					zr.refresh();	
					dancer.dotMove = false;	
				}	
				goFlow.judge.lineDrag = false;
				lineStartJudge.start = false;
				break;	
			default:
				break;
		}
	}
	//步骤双击显示修改步骤名称的div
	function showStepInput(text, x, y){
		stepInput.value = text;
		stepInput.select();
		stepInputDiv.style.cssText = "top:"+ (y + 5) + "px;left:"+ (x + 41)+ "px";	
	}
	//添加步骤边框，适用于添加线段和修改线段的情况。
	function drawStepBorder(type, startPos){
		var shape, xStart, yStart, xEnd, yEnd;
		var pos = startPos;
		var posArr = [], j = 0, id;
		if("img" == type) {
			posArr[0] = pos[0]+88;
			posArr[1] = pos[1]+0;
			posArr[2] = pos[0]+173;
			posArr[3] = pos[1]+19;
			posArr[4] = pos[0]+88;
			posArr[5] = pos[1]+38;
			posArr[6] = pos[0];
			posArr[7] = pos[1]+19;
		}
		else {
			posArr[0] = pos[0]+30;
			posArr[1] = pos[1]+0;
			posArr[2] = pos[0]+60;
			posArr[3] = pos[1]+20;
			posArr[4] = pos[0]+30;
			posArr[5] = pos[1]+40;
			posArr[6] = pos[0];
			posArr[7] = pos[1]+20;	
		}
		for(var i = 0; i <= 3; i++) {
			id = 9001 + i;
			shape = {
				shape : 'circle',
				id : id,
				clickable : false,
				zlevel : 5,
				style : {
					x : 0,
					y : 0,
					r : 10,
					lineWidth : 1,
					brushType : 'stroke',
					strokeColor :'rgb(217, 2, 23)'
				},
				startPos : pos,
				tagType : type,
				position :[posArr[j], posArr[++j]],
				draggable : false,
				needCover : false,
				onmouseover : function(param) {
					_quanInit(param);
				},
				onmouseout : function() {
					lineStartJudge.adjust = false;		
				},
				highlightStyle : {
					lineWidth : 15,
					brushType : "stroke",
					strokeColor :'rgb(250, 126, 75)',
					opacity : '0.5'
				}
			}	
			zr.addShape(shape);
			j++;
		}
		zr.refresh();
		function _quanInit(param) {
			var shape = param.target;
			lineStartJudge.adjust = true;
			if("img" == shape.tagType) {
				switch(shape.id) {
					case 9001:
						lineStartJudge.direction = "top";
						lineStartJudge.pos[0] = shape.startPos[0] + 88;
						lineStartJudge.pos[1] = shape.startPos[1];
						break;	
					case 9002:
						lineStartJudge.direction = "right";
						lineStartJudge.pos[0] = shape.startPos[0] + 176;
						lineStartJudge.pos[1] = shape.startPos[1] + 19;
						break;	
					case 9003:
						lineStartJudge.direction = "bottom";
						lineStartJudge.pos[0] = shape.startPos[0] + 88;
						lineStartJudge.pos[1] = shape.startPos[1] + 38;
						break;	
					case 9004:
						lineStartJudge.direction = "left";
						lineStartJudge.pos[0] = shape.startPos[0];
						lineStartJudge.pos[1] = shape.startPos[1] + 19;
						break;	
				}
			}
			else {
				switch(shape.id) {
					case 9001:
						lineStartJudge.direction = "top";
						lineStartJudge.pos[0] = shape.startPos[0] + 30;
						lineStartJudge.pos[1] = shape.startPos[1];
						break;	
					case 9002:
						lineStartJudge.direction = "right";
						lineStartJudge.pos[0] = shape.startPos[0] + 60;
						lineStartJudge.pos[1] = shape.startPos[1] + 20;
						break;	
					case 9003:
						lineStartJudge.direction = "bottom";
						lineStartJudge.pos[0] = shape.startPos[0] + 30;
						lineStartJudge.pos[1] = shape.startPos[1] + 40;
						break;	
					case 9004:
						lineStartJudge.direction = "left";
						lineStartJudge.pos[0] = shape.startPos[0];
						lineStartJudge.pos[1] = shape.startPos[1] + 20;
						break;	
				}
	
			}
		}
	}
	//删除步骤提示小圆圈
	function delStepBorder() {
		zr.delShape(9001);
		zr.delShape(9002);
		zr.delShape(9003);
		zr.delShape(9004);
		zr.refresh();	
	}
	//步骤移动修改步骤位置
	function upStepPos(id, x, y) {
		var newY, newX, tagRow, id;
		var lastRow = stepObj[id][0];
		var changePostionArr = [];
		var _zr = zr, delRow = false;
		var stepLen = stepArr.length;
		var left, right, bottom, top;
		if(stepArr[2][1] <= y) {
			_zr.modShape(id, {
				position: stepArr[id]	
			});
			tipFont.innerHTML = "Warning, 步骤在Y轴方向应该小于结束点！";
			tipWrap.className = "footer show-block";
			return false;	
		}
		else {
			stepArr[id][0] = x;	
			stepArr[id][1] = y;		
		}	
		newY = stepArr[id][1];
		newX = stepArr[id][0];
		tagRow = Math.floor((newY - stepArr[1][1] - 40)/78);
		//悲剧的事情是这一行只有这一个步骤图形
		if(1 == solidArr[lastRow].length) {
			solidArr.splice(lastRow, 1);
			delRow = true;
		}
		else {
			solidArr[lastRow].splice(stepObj[id][1], 1);
		}
		//判断是否是新插入行，新插入行的条件是该步骤的左上角Y坐标在上一个步骤和下一个步骤之间。
		//放到已有行
		if(tagRow < stepObj[2][0] && newY > (tagRow * 78 + stepArr[1][1] + 80)) {	
			if(delRow && tagRow > lastRow) {
				tagRow = tagRow - 1;	
			}
			tagStepSolid = solidArr[tagRow];
			curRowLen = tagStepSolid.length;
			for(var i = 0; i <= curRowLen; i++) {	
				left = i > 0 ? stepArr[tagStepSolid[i-1]][0] : 0;
				right = i < curRowLen ? stepArr[tagStepSolid[i]][0] : 3000;
				if(left < newX && right > newX) {
					tagStepSolid.splice(i, 0, id); 	
					stepObj[id][1] = i;
				}
				else if(newX < right){
					stepObj[tagStepSolid[i]][1] = stepObj[tagStepSolid[i]][1] + 1;
				}	
			}
		}
		else {
			if(delRow && tagRow > lastRow) {
				tagRow = tagRow - 1;	
			}
			//新插入行。
			if(tagRow >= stepObj[2][0]) {
				solidArr.splice(stepObj[2][0], 0, [id]);
			}
			else {
				solidArr.splice(tagRow, 0, [id]);
			}
			if(tagRow < lastRow) {
				lastRow = lastRow + 1;	
			}
			stepObj[id][0] = tagRow;
			stepObj[id][1] = 0;
		}
		//根据solidArr重新调整页面上图形的位置关系.
		solidSort();
		upRltLine(dba.stepIds);
	}
	//步骤移动修改关联线段
	function upRltLine(stepIds) {
		var rltArr;
		var ids = stepIds.length;
		for(var i = 0; i < ids; i++) {
			rltArrs = dba.stepRlt[stepIds[i]].rltArr;
			for(var key in rltArrs) {
				curRlt = rltArrs[key];
				if("start" == curRlt.type) {
					points = getBrokenPoints(curRlt.startPoint, curRlt.endPoint, curRlt.flwType, curRlt.tagId);
					id = curRlt.lineTag.id;
					zr.delShape(id);						
					dancer.drawBrokenLine(points, curRlt.lineTag.style.opacity, id);
				}		
			}	
		}
	}
	/**
	 *通过solidArr重新调整页面图形的位置。
	*/
	function solidSort() {	
		var _len = solidArr.length;
		var curStepSolid, curRowLen, startX;
		var tempX, tempY;
		var initializeHeight = stepArr[1][1] + 80;
		for(var i = 0; i < _len - 1; i++) {
			curStepSolid = solidArr[i];
			curRowLen = curStepSolid.length;
			startX = stepArr[1][0] - ((curRowLen - 1) * 216 + 176)/2 + 30;
			for(j = 0; j < curRowLen; j++) {
				id = curStepSolid[j];
				tempX = startX + j * 216;
				tempY = initializeHeight + i * 78;
				stepArr[id][0] = tempX;	
				stepArr[id][1] = tempY;
				dba.stepRlt[id].x1 = tempX + dancer.canvasWrap[0] - 10;
				dba.stepRlt[id].x2 = tempX + dancer.canvasWrap[0] + 178 + 10;
				dba.stepRlt[id].y1 = tempY + dancer.canvasWrap[1] - 10;
				dba.stepRlt[id].y2 = tempY + dancer.canvasWrap[1] + 38 + 10;
				stepObj[id][0] = i;
				zr.modShape(id, {
					position:stepArr[id]
				});
				zr.modShape("text_"+id, {
					style : {x : stepArr[id][0] + 150, y:stepArr[id][1]-5}	
				});
			}
		}	
		stepArr[2][1] = initializeHeight + i * 78;
		stepObj[2][0] = i;
		dba.stepRlt[2].y1 = stepArr[2][1] + dancer.canvasWrap[1] - 10;
		dba.stepRlt[2].y2 = stepArr[2][1] + dancer.canvasWrap[1] + 40 + 10;
		zr.modShape(2, {
			style:{ y : stepArr[2][1] + 20} 
		});
	}
	//步骤移动垂直方向上提示线段控制。
	function verticalTip(x, id){
		var tags = dancer.shapList;
		var tags = dba.stepRlt;
		var aligning = false;
		if(x == stepLineTip.x) {
			return;	
		}
		else {
			for(var i = 0, tag; tag = tags[i]; i++) {
				if(tag.id == id) {
					continue;	
				}
				if("ellipseo" == tag.type) {
					if(x == (tag.x1 + 40 - dancer.canvasWrap[0])) {
						aligning = true;
						break;
					}	
				}
				else if("img" == tag.type) {
					if(x == (tag.x1 + 98 - dancer.canvasWrap[0])) {
						aligning = true;
						break;	
					}	
				}	
			}
			if(aligning) {
				zr.modShape("tip01", {
					style : {
						opacity : '100'	
					},
					position : [x, 0]	
				});
				zr.refresh();
				stepLineTip.x  = x;
				setTimeout(function(){
					zr.modShape("tip01", {
						style : {
							opacity : '0'	
						}
					});
					zr.refresh();
				}, 2000);
				return ;	
			}
			if('' != stepLineTip.x) {
				zr.modShape("tip01", {
					style : {
						opacity : '0'	
					},
					position : [x, 0]	
				});
				zr.refresh();
			}
			stepLineTip.x  = '';	
		}
	}	
	//步骤移动水平方向上提示线段控制。
	function levelTip(y, id) {
		var tags = dancer.shapList;
		var tags = dba.stepRlt;
		var aligning = false;
		if(y == stepLineTip.y) {
			return;	
		}
		else {
			for(var i = 0, tag; tag = tags[i]; i++) {
				if(tag.id == id) {
					continue;	
				}
				if("ellipseo" == tag.type) {
					if(y == (tag.y1 + 30 - dancer.canvasWrap[1])) {
						aligning = true;
						break;
					}	
				}
				else if("img" == tag.type) {
					if(y == (tag.y1 + 29 - dancer.canvasWrap[1])) {
						aligning = true;
						break;	
					}	
				}	
			}
			if(aligning) {
				zr.modShape("tip02", {
					style : {
						opacity : '100'	
					},
					position : [0, y]	
				});
				zr.refresh();
				stepLineTip.y  = y;
				setTimeout(function(){
					zr.modShape("tip02", {
						style : {
							opacity : '0'	
						}
					});
					zr.refresh();
				}, 2000)
				return ;	
			}
			if('' != stepLineTip.x) {
				zr.modShape("tip02", {
					style : {
						opacity : '0'	
					},
					position : [0, y]	
				});
				zr.refresh();
			}
			stepLineTip.y  = '';	
		}
	}
	//找到被框选的图形 
	function findRecChoice() {
		var params = arguments, j = 0;
		var stepIds = [], id, stepId, stepIdA;//步骤图形的集合，用于找到关联线段。
		var lineIds = [], brokenIds = [];
		//局部选择初始化，防止不停的框选操作
		partChoice.lineNeed = false;
		partChoice.stepNeed = false;
		partChoice.whichPort.length = 0;
		partChoice.listTag.length = 0;
		for(var i = 0, list; list = dancer.shapList[i++];) {
			if(params[0] <= list.x1 && params[1] >= list.x1 
			  && params[0] <= list.x2 && params[1] >= list.x2  
			  && params[2] <= list.y1 && params[3] >= list.y1 
			  && params[2] <= list.y2 && params[3] >= list.y2) {
				switch(list.type) {
					case "img": 
						if("normal" == list.imgtype) {
							src = "images/ncstep.png";
						}
						else {
							src = "images/dcstep.png";	
						}
						zr.modShape(list.id ,{
							style : {
								image : src						
							}	
						});
						stepIds.push(list.id);
						break;
					case "line"	:
						zr.modShape(list.id, {
							style: {
								strokeColor :'rgb(255, 129, 0)'
							},
							draggable : false
						});	
						lineIds.push(list.id);
						break;
					case "brokenLine" :
						zr.modShape(list.id, {
							style : {
								strokeColor : 'rgb(255, 129, 0)'	
							}
						});	
						brokenIds.push(list.id);
						break;
					default :
						zr.modShape(list.id, {
							style : {
								textColor : 'rgb(255, 129, 0)'	
							}
						})	
						break;
				}
				clickArr[list.id] = list;
				j++;
			}	
		}
		zr.refresh();	
		//当局部框选后，步骤移动也需要移动选中步骤相关联的线段。
		if(j == dancer.shapList.length) {
			return;	
		}
		else {
			for(i = 0, id; id = brokenIds[i++];) {
				stepId = dancer.shapList[id-1].startStep;
				stepIdA = dancer.shapList[id-1].endStep;
				//如果折线的两个链接步骤均为被选中，则不作移动。
				if(undefined == clickArr[stepId] && undefined == clickArr[stepIdA]) {
					clickArr.splice(id-1,1);
				}
			}
			//直接找出需要移动的关联线段。
			for(i = 0, id; id = stepIds[i++];) {
				rltArr = dancer.shapList[id - 1].rltArr;	
				for(var j = 0, rlt;rlt = rltArr[j++];) {
					if(undefined == clickArr[rlt.lineTag.id]) {
						//line对象的时候 直接将rlt推送给partChoice.listTag, 折线这里只给折线点数组。
						partChoice.listTag.push({"type":rlt.type, "arr":brokenPoints[rlt.lineTag.id], "id":rlt.lineTag.id});
					}
				}
			}
			for(i = 0, id; id = lineIds[i++];) {
				stepId = dancer.shapList[id-1].startStep;
				if(undefined == clickArr[stepId]) {
					partChoice.lineNeed = true;
					partChoice.whichPort[id] = "start";
				}
				stepId = dancer.shapList[id-1].endStep;
				if(undefined == clickArr[stepId]) {
					partChoice.lineNeed = true;
					partChoice.whichPort[id] = "end";
				}	 
			}

			if(0 != partChoice.length) {
				partChoice.stepNeed = true;	
			}
		}
	}
	//群体出发
	function groupToMove(id, dx, dy) {
		var clickTag, shapeTag, clickedNum = clickArr.length;
		var rltArr, rlt, j, lineTag, line;	
		totalDx += dx;
		totalDy += dy;
		for(var i = 0; i <= clickedNum; i++) {
			clickTag = clickArr[i];
			if(undefined == clickTag || id == clickTag.id) {
				continue;	
			}
			else {
				shapeTag = clickTag.tag;
				switch(clickTag.type) {
					case "line" :
						port = partChoice.whichPort[clickTag.id];
						if(true == partChoice.lineNeed && undefined != port) {
							if("start" == port) {
								shapeTag.style.endX += dx;
								shapeTag.style.endY += dy;
								shapeTag.style.xEnd += dx;
								shapeTag.style.yEnd += dy;
								zr.modShape(clickTag.id, {
									style : {
										endX : shapeTag.style.endX,
										endY : shapeTag.style.endY,
										xEnd : shapeTag.style.xEnd,
										yEnd : shapeTag.style.yEnd
									}
								});
							}
							else {
								shapeTag.style.startX += dx;
								shapeTag.style.startY += dy;
								shapeTag.style.xStart += dx;
								shapeTag.style.yStart += dy;
								zr.modShape(clickTag.id, {
									style : {
										startX : shapeTag.style.startX,
										startY : shapeTag.style.startY,
										xStart : shapeTag.style.xStart, 
										yStart : shapeTag.style.yStart
									}
								});
							}
						}
						else {			
							shapeTag.position[0] += dx;
							shapeTag.position[1] += dy;
							shapeTag.style.startX += dx;
							shapeTag.style.startY += dy;
							shapeTag.style.endX += dx;
							shapeTag.style.endY += dy;
							zr.modShape(clickTag.id, {
								position : [shapeTag.position[0], shapeTag.position[1]],
								style : {
									startX : shapeTag.style.startX,
									startY : shapeTag.style.startY,
									endX : shapeTag.style.endX,
									endY : shapeTag.style.endY
								}
							});
						}
						break;
					case "img" :
						shapeTag.position[0] += dx;
						shapeTag.position[1] += dy;
						zr.modShape(clickTag.id, {
							position : [shapeTag.position[0], shapeTag.position[1]]	
						});
						break;
					case "brokenLine" :
						port = partChoice.whichPort[clickTag.id];
						if(true == partChoice.lineNeed && undefined != port) {}
						//注： 因折线寻路算法比较复杂而且容易进入死循环，故群体移动时只移动现在的点坐标。
						var listTag = dancer.shapList[clickTag.id-1];
						var point = brokenPoints[clickTag.id];
						for(var j = 0, len = point.length; j < len; j++) {
							point[j][0] += dx;
							point[j][1] += dy;	
						}
						zr.modShape(clickTag.id, {style :{
							pointList :brokenPoints[id] 
							}
						});
						
						//_brokenMovingPoints();
						break;
					case "ellipseo" :
						zr.modShape(clickTag.id, {
							style : {
								x : shapeTag.style.x+dx,
								y : shapeTag.style.y+dy	
							}	
						})
						break;	
				}	
			}	
		}
		if(true == partChoice.stepNeed) {
			for(i = 0, line; line = partChoice.listTag[i++];) {
				//这个地方原是line 图形的移动判断。
/*				if("start" == line.type) {
					line.lineTag.style.xStart += dx;
					line.lineTag.style.yStart += dy;
					line.lineTag.style.startX += dx;
					line.lineTag.style.startY += dy;
					zr.modShape(line.lineTag.id, {
						style : {
							xStart : line.lineTag.style.xStart,
							yStart : line.lineTag.style.yStart,
							startX : line.lineTag.style.startX,
							startY : line.lineTag.style.startY
						}	
					});	
				}	
				else {
					line.lineTag.style.xEnd += dx;
					line.lineTag.style.yEnd += dy;
					line.lineTag.style.endX += dx;
					line.lineTag.style.endY += dy;
					zr.modShape(line.lineTag.id, {
						style : {
							xEnd : line.lineTag.style.xEnd,
							yEnd : line.lineTag.style.yEnd,
							endX : line.lineTag.style.endX,
							endY : line.lineTag.style.endY
						}	
					});		
				}*/
				//这个地方是折线局部运动的逻辑
				brokenPoints[line.id] = _brokenMovingPoints(dx, dy, line);
				zr.modShape(line.id, {
					style : {
						brokenPoints : 	brokenPoints[line.id]
				}});
			}	
		}	
		zr.refresh();
		
		/*核心代码之一，寻路算法二。
		*移动有折线链接的图形算法，拖动中的线段可和已有的图形重叠。该算法计算量较小，只是为了响应用户的拖动，在拖动结束后会用寻路算法一重新生成路径。
		*return: 返回一个折线折点的数组
		*dx, X增加量;
		*dy, Y增加量'
		*line, 折线的移动点和折点数组.
		**************************/
		function _brokenMovingPoints(dx, dy, line) {
			var type = line.type;
			var pointArr = line.arr;
			var len = pointArr.length;
			var tempArr = [];
			if("start" == type) {
				if(pointArr[0][0] == pointArr[1][0]) {
					if(pointArr[0][1] > pointArr[1][1]) {
						//需要判断是否超过默认值，如果超过就需要生成新的节点。
						if(15 > (pointArr[0][1] - pointArr[1][1] + dy)) {
							pointArr[1][1] += dy;
							pointArr[2][1] += dy;	
						}
						else {
							if(pointArr[len-1][1] >= pointArr[0][1]) {
								pointArr[1][1] += dy;
								pointArr[2][1] += dy;	
							}	
						}	
					}
					else {
						if(15 >= (pointArr[1][1] - (pointArr[0][1] + dy))) {
							pointArr[1][1] += dy;
							pointArr[2][1] += dy;	
						}
						else {
							if(pointArr[len-1][1] <= pointArr[0][1]) {
								pointArr[1][1] += dy;
								pointArr[2][1] += dy;	
							}	
						}	
					} 	
					pointArr[0][1] += dy;
					pointArr[0][0] += dx;
					pointArr[1][0] += dx;
				}
				else if(pointArr[0][1] == pointArr[1][1]) {
					if(pointArr[0][0] > pointArr[1][0]) {
						if(15 > (pointArr[0][0] - pointArr[1][0] + dx)) {
							pointArr[1][0] += dx;
							pointArr[2][0] += dx;	
						}
						else {
							//控制0 1两个点之间的距离为15.
							if(pointArr[len-1][0] >= pointArr[0][0]) {
								if((pointArr[0][0] - pointArr[1][0] + dx) > 15) {
									pointArr[1][0] = pointArr[0][0] - 15;
									pointArr[2][0] = pointArr[0][0] - 15;		
								}
								else {
									pointArr[1][0] += dx;
									pointArr[2][0] += dx;	
								}
							}		
						}	
					}
					else {
						if(15 > (pointArr[1][0] - pointArr[0][0] + dx)) {
							pointArr[1][0] += dx;
							pointArr[2][0] += dx;	
						}
						else {
							if(pointArr[len-1][0] >= pointArr[0][0]) {
								//控制0 1两个点之间的距离为15.
								if((pointArr[1][0] - pointArr[0][0] + dx) > 15) {
									pointArr[1][0] = pointArr[0][0] + 15;
									pointArr[2][0] = pointArr[0][0] + 15;	
								}
								else {
									pointArr[1][0] += dx;
									pointArr[2][0] += dx;	
								}
							}	
						}	
					}
					pointArr[0][0] += dx;
					pointArr[0][1] += dy;
					pointArr[1][1] += dy;	
				}	
			}
			len = pointArr.length;
			tempArr[0] = pointArr[0];
			for(var i = 1, j = 1; i < len; i++) {		
				a = pointArr[i-1];
				b = pointArr[i];
				if(a[0] == b[0]) {
					if(undefined != pointArr[i+1] && pointArr[i+1][0] == b[0] && a[1] != pointArr[i+1][1]) {
						tempArr[j] = pointArr[i+1];
						i++;
					}
					else {
						tempArr[j] = b; 	
					}
				}
				else {
					if(undefined != pointArr[i+1] && pointArr[i+1][1] == b[1] && a[0] != pointArr[i+1][0]) {
						tempArr[j] = pointArr[i+1];
						i++;
					}
					else {
						tempArr[j] = b; 	
					}
				}
				j++;
			}		
			return tempArr;
		}
	}

	/**
	 *核心代码之一，寻路算法一。用来生成线段和图形无重叠的算法。
	 *@param: {string} dir1 折线起点在步骤上的位置;
	 *@param: {string} dir2 折线终点在步骤上的位置'
	 *@param: {string} oprType 操作类型，有可能是操作工作3、4、5，也有可能是流转关系M、B、A.
	 *@param: {array} connectTags [0]表示起点图形的ID，[1]表示结束点图形的ID
	 *优化方案：
		 *YOU1：当流转或者归档的下一步是0时，判断是否能够从侧边走，不用默认的折线算法。
		 *YOU2: 同一行两个相邻步骤流转用left或者right点。
		 *YOU3: 当起点在终点的上方的时候可以从两边走。
	 *return: 
	  	返回一个包含折线折点的数组，折线结束点的位置数组
	*/
	function getBrokenPoints(dir1, dir2, oprType, connectTags) {
		var lines = [];
		var lineArr = [];
		var lastPoint = [], tempArr = [];
		var startStep = connectTags[0];//起点的步骤ID
		var endStep = connectTags[1];//终点步骤id
		var _startPos = stepObj[startStep]; 
		var _endPos = stepObj[endStep];
		var _startPoint = new Array(stepArr[startStep][0], stepArr[startStep][1]);
		var _endPoint = new Array(stepArr[endStep][0], stepArr[endStep][1]);
		var needToOptimize = true;
		var dirction = '';//判断起点是在终点的上方还是下方。
		var i = 1, startStepLen, pos1 =[], pos2=[];
		var _solidArr = solidArr;
		var _curBorA, _curBorB, isIn;
		//计算出开始步骤向下遇到的最宽行。
		var _solidLen = _solidArr.length;
		if(1 == startStep) {
			_startPoint[0] -= 58;	
		}
		if(2 == endStep) {
			_endPoint[0] -= 58;	
		}
		//YOU3
		startStepLen = _solidArr[_startPos[0]].length;
		endStepLen = _solidArr[_endPos[0]].length;
		if(_endPoint[1] < _startPoint[1]) {
			for(var leftRow = _startPos[0], maxWidth = 0, _len; leftRow >= 0; leftRow--) {
				_len = _solidArr[leftRow].length;
				if(maxWidth <= _len) {
					maxWidth = _len;
					maxNum = leftRow;
				}	
			}	
			if(maxNum == _startPos[0]) {
				needToOptimize = false;
			}
			_curBorA = stepArr[1][0] + ((maxWidth - 1)*216 + 176)/2 + 45;
		 	_curBorB = stepArr[1][0] - ((maxWidth - 1)*216 + 176)/2 + 15;

			if(_startPoint[0] <= _endPoint[0]) {
				if(_endPos[1] == endStepLen - 1 && _startPos[1] == startStepLen - 1) {
					dir1 = "right";
					dir2 = "right";	
					if(needToOptimize) {
						points = [[_startPoint[0] + 176, _startPoint[1]+19], [_startPoint[0] + 191, _startPoint[1]+19], [_curBorA, _startPoint[1]+19], [_curBorA, _endPoint[1]+19], [_endPoint[0]+191, _endPoint[1]+19], [_endPoint[0]+176, _endPoint[1]+19]];
						return points;
					}
				}
				else {
					dir1 = "left";
					dir2 = "left";
					if(0 == _startPos[1] && 0 == _endPos[1]) {
						points = [[_startPoint[0], _startPoint[1] + 19], [_curBorB, _startPoint[1]+19], [_curBorB, _endPoint[1]+19], [_endPoint[0], _endPoint[1]+19]];						return points;
					}
				}
			}

			if(_startPoint[0] > _endPoint[0]) {
				if((_endPos[1] == endStepLen - 1 || (_endPos[1] == 0 && endStepLen == 1))) {
					dir1 = "right";
					dir2 = "right";	
					if(needToOptimize) {
						points = [[_startPoint[0] + 176, _startPoint[1]+19], [_startPoint[0] + 191, _startPoint[1]+19], [_curBorA, _startPoint[1]+19], [_curBorA, _endPoint[1]+19], [_endPoint[0]+191, _endPoint[1]+19], [_endPoint[0]+176, _endPoint[1]+19]];	
						return points;
					}
				}
				else if(_endPoint[0] < _startPoint[0]) {
					if(0 == _startPos[1] && 0 == _endPos[1]) {
						points = [[_startPoint[0], _startPoint[1] + 19], [_curBorB, _startPoint[1]+19], [_curBorB, _endPoint[1]+19], [_endPoint[0], _endPoint[1]+19]];
						return points;
					}
					dir1 = "left";
					if(176 >  _startPoint[0] - _endPoint[0]) {
						dir2 = "left";		
					}
					else {
						dir2 = "right";
					}
				}
			}					

		}
		else {
			if(_startPos[0] != _solidArr.length - 2) {
				for(var leftRow = _startPos[0], maxWidth = 0, _len;leftRow < _solidLen;leftRow++) {
					_len = _solidArr[leftRow].length;
					if(maxWidth <= _len) {
						maxWidth = _len;
						maxNum = leftRow;
					}	
					if(_len >= startStepLen) {
						needToOptimize = false;
					}
				}			 
				_curBorA = stepArr[1][0] + ((maxWidth - 1)*216 + 176)/2 + 45;
		 		_curBorB = stepArr[1][0] - ((maxWidth - 1)*216 + 176)/2 + 15;
			}	
		}

		//YOU1
		//能够进行优化的条件如下：N或者A的下一步是0，且该步骤在该行的第一个或者最后一个
		if(2 == endStep && _startPos[0] != _solidArr.length - 2) {
			pos1 = [_startPoint[0] + 88, _startPoint[1] + 38];
			pos2 = [_endPoint[0], _endPoint[1]];
			if(solidArr[_startPos[0]].length - 1 == _startPos[1]) {
				if(_startPos[0] >= maxNum && "bottom" == dir1) {
						//points = [[pos1[0], pos1[1]], [pos1[0], pos1[1]+15], [pos1[0] + 103, pos1[1]+15], [pos1[0] + 103, pos2[1]+20], [pos2[0]+120, pos2[1]+20]];
						points = [[pos1[0], pos1[1]], [pos1[0], pos1[1]+15], [pos1[0], pos2[1]+20], [pos2[0]+120, pos2[1]+20]];
						return points;
				}
				else {
					if("right" == dir1) {
						pos1 = [_startPoint[0] + 176, _startPoint[1] + 19];
						points = [[pos1[0], pos1[1]], [pos1[0] + 15, pos1[1]], [_curBorA, pos2[1]+20], [pos2[0]+140, pos2[1]+20], [pos2[0]+120, pos2[1]+20]];
					}
					else {
						points = [[pos1[0], pos1[1]], [pos1[0], pos1[1]+15], [_curBorA, pos1[1]+15], [_curBorA, pos2[1]+20], [pos2[0]+120, pos2[1]+20]];
					}
					return points;
				}
			}
			else if(0 == _startPos[1]){
				if(_startPos[0] >= maxNum && "bottom" ==  dir1) { 
					points = [[pos1[0], pos1[1]], [pos1[0], pos1[1]+15], [pos1[0], pos1[1]+15],  [pos1[0], pos2[1]+20], [pos2[0]+58, pos2[1]+20]];
				}
				else {
					pos1 = [_startPoint[0], _startPoint[1]];
					pos2[0] = pos2[0] + 58; 
					points = [[pos1[0], pos1[1]+19], [_curBorB, pos1[1]+19], [_curBorB, pos2[1]+20], [pos2[0]-15, pos2[1]+20], [pos2[0], pos2[1]+20]];	
				}
				return points;
			}	
		}
		//YOU2 
		//两个步骤同行且相邻直接用left和right
		if(_startPos[0] == _endPos[0]){	
			//左边
			if(_startPos[1] == _endPos[1]+1) {
				points = [[_startPoint[0], _startPoint[1]+19], [_startPoint[0]-15, _startPoint[1] + 19], [_endPoint[0] + 191, _endPoint[1] + 19], [_endPoint[0] + 176, _endPoint[1] + 19]];
				return points;
			}
			else if(_startPos[1] == _endPos[1]-1) {
				points = [[_startPoint[0] + 176, _startPoint[1]+19], [_startPoint[0]+ 191, _startPoint[1] + 19], [_endPoint[0] - 15, _endPoint[1] + 19], [_endPoint[0], _endPoint[1] + 19]];
				return points;
			}	
			
			if(_startPos[1] > _endPos[1]) {
				dir1 = "left";	
			}
			else {
				dir1 = "right";	
			}
		}
		switch(dir1) {
			case "top" :
				lineArr[0] = [_startPoint[0] + 88, _startPoint[1]];
				lineArr[i] = [_startPoint[0] + 88, _startPoint[1] - 15]; 
				break;
			case "right" : 	
				lineArr[0] = [_startPoint[0] + 176, _startPoint[1] + 19];
				lineArr[i] = [_startPoint[0] + 191, _startPoint[1] + 19];
				break;
			case "bottom" :
				lineArr[0] = [_startPoint[0] + 88, _startPoint[1] + 38];
				lineArr[i] = [_startPoint[0] + 88, _startPoint[1] + 53];
				break;
			case "left" :
				lineArr[0] = [_startPoint[0], _startPoint[1] + 19];
				lineArr[i] = [_startPoint[0] - 15, _startPoint[1] + 19];
				break;
		}

		switch(dir2) {
			case "top" :
				lastPointA = [_endPoint[0] + 88, _endPoint[1] - 15]; 
				lastPointB = [_endPoint[0] + 88, _endPoint[1]]; 
				break;
			case "right" : 
				lastPointA = [_endPoint[0] + 191, _endPoint[1] + 19];	
				lastPointB = [_endPoint[0] + 176, _endPoint[1] + 19];
				break;
			case "bottom" :
				lastPointA = [_endPoint[0] + 88, _endPoint[1] + 53];
				lastPointB = [_endPoint[0] + 88, _endPoint[1] + 38];
				break;
			case "left" :
				lastPointA = [_endPoint[0]-15, _endPoint[1] + 19];
				lastPointB = [_endPoint[0], _endPoint[1] + 19];
				break;
		}
		i++;
		if(lineArr[1][1] > lastPoint[1]) {
			direction = "down";	
		}		
		else {
			direction = "up";	
		}
		_checkOneLine();
		_rectangleWay(lineArr[1], lastPointA);
		lineArr.push(lastPointA);
		lineArr.push(lastPointB);
		return noRepeatPoint(lineArr);
		/**
		 *矩形框寻路
		 *@param {array} a 下一个矩形框的开始点
		 *@param {array} b 最终的结束点
		*/
		function _rectangleWay(a, b) {
			var i = 0, points = [];
			var j, lineA, lineB;
			var firstStep, len;
			points[0] = [[a[0],a[1]], [b[0], a[1]]];
			points[1] = [[a[0],a[1]], [a[0], b[1]]];
			do {
				_checkStepOnline(points[i][0], points[i][1], i);
				++i;	
			}while(i<=1)
			//根据lines判断使用哪条路径。
			if(0 == lines[0].length && a[0] != b[0]) { //a[0] == b[0] 表示在同一条线上，不做判断
				len = lineArr.length;
				//如果b[0]在前2个点之间则不用这条路径
				if(lineArr[len-1][0] > b[0] && lineArr[len-2][0] < b[0]
					|| lineArr[len-1][0] < b[0] && lineArr[len-2][0] > b[0]) {
				}
				else {
					isIn = _checkStepOnline([b[0], a[1]], [b[0], b[1]], 0)
					//game over? not over!
					if(!isIn) {	
						if(0 == lines[1].length) { //对于矩形4个边框上都没有步骤的情况，使用节点最少的情况。
							lineArr.push([a[0], b[1]]);
						}
						else {
							lineArr.push([b[0], a[1]]);
						}
						return;
					}
				}
			}
			if(0 == lines[1].length && a[1] != b[1]) { //a[1] == b[1] 表示在同一条线上，不做判断
				isIn = _checkStepOnline([a[0], b[1]], [b[0], b[1]], 1);
				//game over
				if(!isIn) {
					lineArr.push([a[0], b[1]]);
					return;
				}
			}
			/*根据垂直方向找出下一个点的坐标。
			*先计算垂直方向的坐标差额，小于或等于固定值就横向移动，否则垂直移动。
			*/	
			//↓方向
			if(b[1]>a[1]) {
				//这里保证竖线上的点一定到达。
				if(15 < (lines[1][1] - a[1])) {
					lineArr.push([a[0],lines[1][1] - 15]);		
				}								
				//←方向	
				if(a[0] > b[0]) {
					lineArr.push([lines[1][0] - 15, lines[1][1] - 15]);	
					arguments.callee([lines[1][0] - 15, lines[1][1] - 15], lastPointA);	
				}
				//→方向
				else{
					lineArr.push([lines[1][0]+191, lines[1][1] - 15]);	
					arguments.callee([lines[1][0] + 191, lines[1][1] - 15], lastPointA);	
				}	
			}
			//↑方向
			else {
				if(15 < (a[1] - lines[1][1]+38)) {
					lineArr.push([a[0],lines[1][1] + 53]);		
				}									
				if(a[0] > b[0]) {
					lineArr.push([lines[1][0] - 15, lines[1][1] + 53]);
					arguments.callee([lines[1][0] - 15, lines[1][1] + 53], lastPointA);	
				}
				else {
					lineArr.push([lines[1][0]+191, lines[1][1] + 53]);	
					arguments.callee([lines[1][0] +191, lines[1][1] +53], lastPointA);	
				}		
			}
		}
		/**
		 *判断线段有没有和步骤重叠。
		 *调用1：统计a, b所构成的方框2条边上重叠步骤图形
		 *调用2：检测a, b所构成的直线上是否有步骤图形
		 *@param {array} a 方框的一个角的坐标
		 *@param {array} b 方框对应a点的角的坐标
		 *@param {string} i 调用1时表示lines的键值，调用2时无实际意义，所以此时传入值为0。
		*/
		function _checkStepOnline(a, b, i) {
			var pointA, pointB, len;
			lines[i] = [];
			var isIn = false;//当初始两条线中任意一条没有步骤图形时 在检测相邻边时返回用。
			//竖线判断
			if(a[0] == b[0]) {
				pointA = a[1] > b[1] ? b[1] : a[1];
				pointB = b[1] > a[1] ? b[1] : a[1];
				len = stepArr.length;
				for(var j = 0, step;j < len;j++) {
					step = stepArr[j];
					if(undefined == step || 1 == j || 2 == j) {
						continue;	
					}
					else {
						if((step[0] <= a[0] && a[0] <= step[0] + 176) && (
							(pointA <= step[1] && pointB >= step[1] && 
							pointA <= step[1] + 38 && pointB >= step[1] + 38) ||
							(pointA >= step[1] && pointA <= step[1] + 38) ||
							(pointB >= step[1] && pointB <= step[1] + 38))) {
							isIn = true;
							if(j == startStep) {
								lines[i] = step;
								return ++i;
							}
							else {
								if(0 == lines[i].length) {
									lines[i] = step;	
								}
								else {
									//↓走向
									if(b[1] > a[1]) {
										if(lines[i][1] > step[1]) {
											lines[i] = step;
										}
									}
									else {//↑走向
										if(lines[i][1] < step[1]) {
											lines[i] = step;
										}	
									}
								}
							}	 
						}
					}
				}
			}
			else if(a[1] == b[1]) {
				pointA = a[0] > b[0] ? b[0] : a[0];
				pointB = a[0] > b[0] ? a[0] : b[0];
				var arrLen = stepArr.length;
				for(j = 0, step;j < arrLen;j++) {
					step = stepArr[j];
					if(undefined == step || 1 == j || 2 == j) {
						continue;	
					}
					else {
						if((step[1] <= a[1] && step[1]+38 >= a[1])
							&& ((pointA <= step[0] && pointB >= step[0] && pointA <= step[0]+ 176 && pointB >= step[0] + 176)
								|| (pointA >= step[0] && pointA <= step[0] + 176)
								|| (pointB >= step[0] && pointB <= step[0] + 176))) {
							isIn = true;
							if(j == startStep) {
								lines[i] = step;
								return ++i; 
							}
							else {
								if(0 == lines[i].length) {
									lines[i] = step;	
								}
								else {
									//→走向
									if(b[0] > a[0]) {
										if(lines[i][0] > step[0]) {
											lines[i] = step;	
										}
									}
									else {//←走向
										if(lines[i][0] < step[0]) {
											lines[i] = step;	
										}	
									}
								}
							}	   
						}	
					}
				}
			}
			return isIn;
		}
		/**
		 *避免起点和终点在同一条直线上。
		 *方案：
		 	1，垂直方向：如果起点在第一列终点修改为left，否则就改为right
			2, 水平方向：终点修改为top
		*/
		function _checkOneLine() {
			if(lineArr[1][0] == lastPointA[0] && 2 != endStep) {
				isIn = _checkStepOnline(lineArr[1], lastPointA, 0);
				if(!isIn) {
					return;	
				}
				if(2 == endStep) {
						//endPoint[0] = endPoint[0] - 58;
				}
				if(0 == _startPos[1]) {
					lastPointA = [_endPoint[0] - 15, _endPoint[1] + 19];
					lastPointB = [_endPoint[0], _endPoint[1] + 19];	
				}
				else {
					lastPointA = [_endPoint[0] + 191, _endPoint[1] + 19];	
					lastPointB = [_endPoint[0] + 176, _endPoint[1] + 19];	
				}
				return;	
			}	
			if(lineArr[1][1] == lastPointA[1]) {
				lastPointA = [_endPoint[0] + 88, _endPoint[1] - 15]; 
				lastPointB = [_endPoint[0] + 88, _endPoint[1]]; 	
			}
		}
	}
	/**
	 *合并，消除折线数组的重复点。
	 *@param {array} source 折线算法生成的粗犷折点数组
	 *功能：1，折线数组排除连续3个点X或者Y相同的情况，但是保留第1和第2个点。
	 *      2，连续两个点在 x 或者 y轴上相差不超过5个像素就合并
	        3，数组0, 1, array.length-1, array.length-2 这四个点不能做任何改动。
			4， 如果3这个点和0， 1两个点在同一线段上则保留3这个点；
			5，array.length-3这个点和array.length-2、array.length-1在同一条线段上也保留。
	*/
	function noRepeatPoint(source) {
		var len = source.length;
		var temp, tempArr = [];
		tempArr[0] = source[0];
		tempArr[1] = source[1];
		for(var i = 1; i < len - 2; i++) {
			a = source[i];
			b = source[i+1];
			if(0 < b[0]-a[0] && b[0]-a[0] <= 5 
				|| a[0] - b[0] <= 5 && a[0] - b[0] > 0) {
				if(a[1] == source[i+2][1]) { //3点一线 交由下个循环处理。
					continue;	
				}	
				if(i == len - 3 && source[len-2][0] == source[len - 1][0]) {  
					source[i-1][0] = b[0]; 
					source.splice(i, 1);
					break;
				}
				type = 	"x";	
				_mergePoint(i, type);
				continue;
			}
			if( 0 < b[1]-a[1] && b[1]-a[1] <= 5 
				|| a[1] - b[1] <= 5 && a[1] - b[1] > 0) {
				if(a[0] == source[i+2][0]) { //3点一线 交由下个循环处理。
					continue;	
				}
				if(i == len - 3 && source[len-2][1] == source[len - 1][1]) { 
					source[i-1][1] = b[1];	
					source.splice(i, 1);
					break;
				}
				type = "y";
				_mergePoint(i, type);
			}	 
		}
		len = source.length;
		for(i = 2, j = 2; i < len-2; i++) {		
			a = source[i-1];
			b = source[i];
			if(a[0] == b[0] && a[1] == b[1]) {
				continue;	
			}
			if(a[0] == b[0]) {
				while(b) {
					if(b[0] == a[0]) {
						b = source[++i];	
					}	
					else {
						i--;
						tempArr.push(source[i]);
						break;	
					}
				}
				continue;
			}
			else if(a[1] == b[1]){
				while(b) {
					if(b[1] == a[1]) {
						b = source[++i];	
					}	
					else {
						i--;
						tempArr.push(source[i]);
						break;	
					}
				}
				continue;
			}
		}	
		temp = tempArr.pop();
		if(temp[0] != source[len - 2][0] || temp[1] != source[len - 2][1]) {
			tempArr.push(temp);
		}
		tempArr.push(source[len-2]);
		tempArr.push(source[len-1]);
		return tempArr;
		function _mergePoint(curNum, type) {
			source.splice(curNum+1, 1); //先删除curNum+1这个点
			len = len - 1;	
			var nextPoint = source[curNum+1];
			if("x" == type) {
				if(	len - 2 == curNum+1) {
					source[curNum][0] = nextPoint[0];
				}
				else {
					nextPoint[0] = source[curNum][0];
				}
			}	
			else {
				if(len - 2 == curNum + 1) {
					source[curNum][1] = nextPoint[1];	
				}
				else {
					nextPoint[1] = source[curNum][1];
				}
			}
			//某些情况下，类似于 巨型 下个点是可以删除的。
			if(undefined != source[curNum+2]) {
				if(nextPoint[0] != source[curNum+2][0] || nextPoint[1] != source[curNum+2][1]) {
					
				}
				else {
					source.splice(curNum+1, 1);	
					len = len -1;		
				}
			}
		}
	}
	/*受控模式下，新增步骤或者重新调整位置时具体步骤位置计算。
	*说明：该函数既用来新增步骤时位置调整， 又流程关系转图形时，重新定位。
		   考虑到步骤图形的两种添加，这里把stepObj，solidArr，stepObj都统一更新。
	*参数：x, 鼠标点击的x坐标；
		  y, 鼠标点击的Y坐标；
		  num, 当前类型操作num || 动态步骤或者正常步骤的值;
		  id, 新增图形的ID
		  stepId, 步骤号；
		  stepName, 步骤名称。
	**********************************************/
	function controlModelPos(x, y, num, id, stepNum, stepName) {
		var len, lastRow, i=0, tempId;
		var tempArr = [], row, right, startX;
		var x, y, initializeHeight;
		var leftWrap = dancer.canvasWrap[0];
		var topWrap = dancer.canvasWrap[1];
		if(0 == solidArr.length) {
			solidArr.push([id]);
			initializeHeight = stepArr[1][1] + 178;
			dancer.drawStep(stepArr[1][0] - 58, stepArr[1][1] + 80, num, id, stepNum, stepName);
			stepObj[id] = [0, 0];
		}
		else {
			solidArr.pop();
			row = Math.ceil((y - stepArr[1][1] - 40)/78);
			//新增行。
			if(undefined == solidArr[row-1]) {
				do{
					if(undefined == solidArr[row]) {
						continue;	
					}	
					else {
						lastRow = row + 1;
						solidArr[lastRow] = [];
						solidArr[lastRow].push(id);
						stepObj[id] = [lastRow, 0];
						dancer.drawStep(stepArr[1][0] - 58, stepArr[1][1] + lastRow * 78 + 80, num, id, stepNum, stepName);
						break;
					}
				}
				while(row--);
			}
			else {
				//对于已有的行，仍需要做判断：是添加到该行还是在该行之上新增行。
				newY = y - (stepArr[1][1] + 40) - (row - 1) * (modelTarget.vertical + 38); //newY 小于 40 就新插入一行，否则放到已有行。
				if(newY >= 40) {
					tempArr = solidArr[row-1];
					len = tempArr.length;
					do{
						left = i > 0 ? stepArr[tempArr[i-1]][0] : 0;
						right = i < len ? stepArr[tempArr[i]][0] : 3000;
						if(x > left && x < right) {
							stepObj[id] = [row-1, i];
							tempArr.splice(i, 0, id); 	
							break;
						}
						i++;
					}while(i<=len);
					//计算起点坐标.
					startX = stepArr[1][0] - (len * 216 + 176)/2;
					len = len + 1;
					for(var i = 0, j; i < len; i++) {
						if(undefined == stepArr[tempArr[i]]) {
							j = i;
							continue;	
						}	
						else {
							tempId = tempArr[i];
							stepObj[tempId] = [row-1, i];
							stepArr[tempId][0] = x = startX + i * 216 + 30;
							stepArr[tempId][1] = y = stepArr[1][1] + row * 78 + 2;
							zr.modShape(tempId, {
								position : stepArr[tempId]
							});	
							zr.modShape("text_"+tempId, {
								style : {x:stepArr[tempId][0]+150, y:stepArr[tempId][1] - 5}	
							})
							listTarget = dba.stepRlt[tempId];
							listTarget.x1 = x - 10 + leftWrap;
							listTarget.x2 = x + 186 + leftWrap;
							listTarget.y1 = y - 10 + topWrap;
							listTarget.y2 = y + 48 + topWrap;
						}
					}
					dancer.drawStep(startX + j * 216 + 30,  stepArr[1][1] + row * 78 + 2, num, id, stepNum, stepName);
				}
				else {
					solidArr.splice(row - 1, 0, [id]);
					stepObj[id] = [row - 1, 0];
					dancer.drawStep(stepArr[1][0] - 58, stepArr[1][1] + row * 78 + 80, num, id, stepNum, stepName);
					solidArr.push([2]);
					solidSort();
					return;
				}
			}	
			len = solidArr.length;
			initializeHeight = stepArr[1][1] + 40 + len * (modelTarget.vertical + 38) + modelTarget.vertical + 20;
		}
		//对结束图形进行统一处理。
		solidArr.push([2]);
		zr.modShape(2, {
			style : {y : initializeHeight}	
		});
		stepObj[2][0] = solidArr.length - 1;
		stepArr[2][1] = initializeHeight - 20;
		dba.stepRlt[2].y1 =  initializeHeight - 30 + topWrap;
		dba.stepRlt[2].y2 = initializeHeight + 30 + topWrap;
	}
	/*两种生成连线方式，连线属性整理函数.*/
	function linePropertyReady(_startDir, _endDir, rlttp, _listId, opacity) {
		var points = getBrokenPoints(_startDir, _endDir, rlttp, _listId);
		var tag = dancer.drawBrokenLine(points, opacity);
		var id = tag.id;
		var first = brokenPoints[id][0]; 
		var last = brokenPoints[id][brokenPoints[id].length - 1]; 
		dba.lineRlt[tag.id] = {
			"type" : "brokenLine",
			"startDir" : _startDir,
			"startStep" : _listId[0],
			"endDir" : _endDir,
			"endStep" : _listId[1],
			"id" : id,
			"tag" : tag,
			"x1" : first[0],
			"y1" : first[1],
			"x2" : last[0],
			"y2" : last[1]
		}
		return tag;
	}
	/******************接口区域*****************/
	/**********接口一：已有流程转流程图*********
	*参数 , 从数据库数据整理出的无重叠步骤数组，数组的某个键值可能含有多个步骤。即同一行有多个步骤。
	*思路, 这里借用controlModelPos来生成有标准位置的步骤图形。
	***************************************/
	function flowToPic(steps, relMax, mainFlw, maxNum){
		var rows = steps.length;
		var startX = stepArr[1][0];
		var startY = stepArr[1][1];
		var x, y, num, id, a;
		var tempArr, tempLen;
		var step = dba.step;
		var _steps = [];
		var stepPos = [];

		//针对某些情况，主流程中0不是最后一位。
		if(0 == mainFlw[mainFlw.length-1]) {
			rows -= 1;	
		}
		//根据行调整结束点的位置。
		var yChange = stepArr[1][1] + rows * 78 + 100;
		zr.modShape(2, {
			style : {y:yChange}	
		});
		stepObj[2] = [rows - 1, 0];
		dba.stepRlt[2].y1 = yChange - 30 + dancer.canvasWrap[1];
		dba.stepRlt[2].y2 = yChange + 30 + dancer.canvasWrap[1];
		stepArr[2][1] = yChange - 20;
		for(var i = 0; i < rows; i++) {
			if(1 < steps[i].length) {
				y = startY + i * 78 + 110;
				tempArr = steps[i];
				tempLen = tempArr.length;
				for(var j = 0; j < tempLen; j++) {
					id = zr.newShapeId();
					x = startX + 1000;
					a = step[steps[i][j]];
					num = 0 == a[8] ? 1 : 2;
					controlModelPos(x, y, num, id, a[0], a[4]);	
				}	
			}
			else {
				id = zr.newShapeId();
				y = startY + i * 78 + 110;
				x = startX;	
				a = step[steps[i][0]];
				num = 0 == a[8] ? 1 : 2;
				controlModelPos(x, y, num, id, a[0], a[4]);
			}	
		}
		//solidArr.push([2]);
		drawConnectLine(dba.stepIds, dba.stepDel);    //添加连线
		for(i in dba.stepRlt) {
			tempArr = dba.stepRlt[i];
			if(undefined != tempArr.stepNum)  {
				dancer.drawStepNum(tempArr.id, stepArr[tempArr.id], tempArr.stepNum); // 添加步骤号
			}
		}
		zr.refresh();
	}
	/**
	*	添加步骤之间的连接线
	*@param {array} _steps 已添加步骤对象的图形ID号
	*@param {object} stepDel 每个步骤的具体流转关系
	*_steps, 每个步骤对应的图形ID
	*stepNum, 当前循环中的步骤号
	*stepRel, 根据stepDel得到的当前步骤的流转关系
	*curRel, 当前步骤的某条关系。
	*tempRltA, 起点步骤List里面的关系
	*tempRltB, 终点步骤list里面的关系。
	*******************************************/
	function  drawConnectLine(_steps, stepDel) {
			var _startDir, _endDir, _line, tempTag = {};
			var _startPos = {}, _endPos = [], _listId = [];
			var _listTag = dba.stepRlt;
			var _listLen = _listTag.length;
			var stepLen = _steps.length;
			var tempPos, continueNext;
			var stepNum, stepRel, opacity;
			var tempRltA, tempRltB, lineTag;
			
			points = getBrokenPoints("bottom", "top", 4, [1,3]);
			dancer.drawBrokenLine(points,1); //开始和第一步的连线。
			
			for(var i = 0, j; i<stepLen; i++) {
				_listId.length = 0;
				pos = stepArr[_steps[i]];    //取当前步骤的位置
				stepNum = _listTag[_steps[i]].stepNum;
				stepRel = stepDel[stepNum];	
				_listId[0] = _steps[i];
				for(var num in stepRel) {
					tempRltA = {};
					tempRltB = {};
					curRel = stepRel[num];
					continueNext = false;
					if("B" == curRel.rlttp
						|| "M" == curRel.rlttp
						|| "N" == curRel.rlttp
						|| "A" == curRel.rlttp) {
						for(j in _listTag) {
							tag = _listTag[j];
							if(undefined == tag.stepNum) {
								j++;
								continue;	
							}
							else {
								if(curRel.stpchid == tag.stepNum) {
									_listId[1] = tag.id;
									break;	
								}	
							}	
						}
						
						switch(curRel.rlttp) {
							case "B":
								opacity = 0.1;
								_startDir = "left";
								_endDir = "left";
								break;
							case "M":
								opacity = 0.1;
								_startDir = "right";
								_endDir = "right";
								break;
							case "N":
							case "A":
								opacity = 1;
								_startDir = "bottom";
								_endDir = "top";
								//优化方案1：结束步骤线段到"结束"图形，尽量避免线段走步骤图形内部
								if(0 == curRel.stpchid) {
									_listId[1] = 2;
								}
								break;
						}		
						if(_listId[0] == _listId[1]) {
							continue;
						}
						lineTag = linePropertyReady(_startDir, _endDir, curRel.rlttp, _listId, opacity);
						//here添加list关系
						tempRltA = {
							"type" : "start",
							"flwType" : curRel.rlttp,
							"startPoint" : _startDir,
							"endPoint" : _endDir,
							"lineTag" : lineTag,
							"tagId" : [_listId[0], _listId[1]],
							"stepNum" : [stepNum, tag.stepNum] 
						};
						tempRltB = {
							"type" : "end",
							"flwType" : curRel.rlttp,
							"startPoint" : _startDir,
							"endPoint" : _endDir,
							"lineTag" : lineTag,
							"tagId" : [_listId[0], _listId[1]],
							"stepNum" : [stepNum, tag.stepNum]
						}
						dba.stepRlt[_listId[0]].rltArr.push(tempRltA);
						dba.stepRlt[_listId[1]].rltArr.push(tempRltB);
					}
					else {
							
					}
				}
			}
		}	
	//观察者
	observer = function(){
		return new observer;//jquery式 无new实力化	
	}
	observer.readyPublish = [];
	//订阅
	observer.addSubscriber = function(callback) {
		this.suberscribers = [],
		this.suberscribers[this.suberscribers.length] = callback;
	}
	//退订
	observer.removeSuberscriber = function(callback) {
		for(var i = 0, suber; suber = this.subscribers[i++];) {
			if(suber == callback) {
				delete suber;	
			}	
		}	
	}
	//发布
	observer.publish = function() {
		for(var i = 0, puber; puber = this.readyPublish[i++];) {
			this.suberscribers[0](mes);
			puber.tag.suberscribers[0](data);	
		}
	}
	//将对象o具有观测者功能
	observer.make = function(o) {
		for(var i in this) {
			o[i] = this[i];
			o.subscribers = [];	
		}
	}
	//获取发布者并绑定事件
	//**********************
	/*changeType 3个状态”
	/*为空表示表单所在的数据项是第一次出现，sameType表示相同数据项已经出现，changed表示该表单在一次保存中出现过多次。
	//**************************/
	observer.setPuber = function(tags) {
		for(var i = 0, tag; tag = tags[i++];) {
			if(tag.getAttribute("type") != "checkbox") {
				tag.onchange = function() {
					observer.monitoring(this);
				}
			}
		}
	}
	observer.monitoring = function(that) {
		var data = {}, name, m, k, tempType, trRow;
		var reg, changeType, reader, parentRow, val;
		changeType = "default";
		name = that.name.split("_");
		switch(name[0]) {
			case "miao":
			case "yewu":
			case "flw":
				tempType = name[0];
				break;
			case "step":
				parentRow = that.parentNode.parentNode;
				trRow = parentRow.rowIndex;
				tempType = "step" + "_" + trRow;
				break;
			case "quan":
				parentRow = that.parentNode.parentNode;
				trRow = parentRow.parentNode.rows.length - parentRow.rowIndex;
				tempType = "quan" + "_" + trRow;
			default:
				break;	
		}		
		data.changeName = name[1];
		if("flw_check" == that.className) {
			if(that.checked) {
				data.changeVal = 1;
			}	
			else {
				data.changeVal = 0;	
			}
		} else {
			data.changeVal = that.value.Trim();
		}
		for(var j in observer.readyPublish) {
			reader = observer.readyPublish[j];
			if(tempType == reader.type && "update" == reader.data.type) {
				if(0 <= reader.data.change.indexOf(name[1])) {
					changeType = "changed";	
					m = j;
					for(var n = 0, named; named = reader.data.tags[n++];) {
						if(that.name == named.name) {
							k = n - 1;
							break;
						}	
					}
					break;
				}
				else {
					changeType = "sameType";
					m = j;	
				}	
			}
			else if("insert" == reader.data.type && tempType == reader.type){
				var tempArr = reader.data.change.split(",");
				tempArr[that.parentNode.cellIndex] = "\"" + data.changeVal + "\"";
				reader.data.change = tempArr.join(",");
			}
		}
		switch(changeType) {
			case "changed":	
				reg = new RegExp(name[1]+'=\"(.*?)\"');
				if(data.changeVal == dba.monitoring.checkVal) {
					observer.readyPublish[m].data.change = observer.readyPublish[m].data.change.replace(reg, "");
					observer.readyPublish[m].data.tags.splice(k, 1);
					//如果是最后一个，就把该条数据删除
					if(0 == observer.readyPublish[m].data.tags.length) {
						observer.readyPublish.splice(m, 1);	
					}
				}
				else {
					observer.readyPublish[m].data.change = observer.readyPublish[m].data.change.replace(reg, name[1]+"=\""+data.changeVal+"\"");
				}
				break;
			case "sameType":
				observer.readyPublish[m].data.change += ","+	name[1]+"=\""+data.changeVal +"\"";
				var len = observer.readyPublish.length;
				observer.readyPublish[m].data.tags[observer.readyPublish[m].data.tags.length] = that;
				break;
			case "default":
				//对于日历插件这种改变input的值，但是最终的值又和默认值一样的情况(会触发onchange事件)，不需要保存到变动数组(readyPublish)里面
				if("time" == that.getAttribute("field")) {
					if(that.value == dba.monitoring.checkVal) {
						return false;	
					}
				}
				//构建每个更新的sql语句
				switch(name[0]) {
					case "flw":
						data.head = "UPDATE BAS_WMFSTEPOBJ SET";
						data.where = " WHERE STPID" + "=\"" + $("stpid").value + "\"";
						break;
					//对于步骤流转信息和权限多行信息，用行号来确定。
					case "step":
						data.head = "UPDATE BAS_WMFSTEPRLT SET";
						//这个地方考虑全删全插
						//data.where = " WHERE STPCHID=\"" + parentRow.cells[6].getElementsByTagName("input")[0].value + "\" AND OPCON=\"" + parentRow.cells[6].getElementsByTagName("input")[0].value + "\"";
						break;
					case "quan":
						data.head = "UPDATE BAS_PRVOBJSLV SET";
						data.where = " WHERE PRVTYPE=\"" + parentRow.cells[3].getElementsByTagName("SELECT")[0].value + "\" AND GUPNUM=\"" + parentRow.cells[4].getElementsByTagName("input")[0].value + "\" AND HDSQLCON=\"" + parentRow.cells[5].getElementsByTagName("input")[0].value + "\" AND OID=\""+$("OID").value +"\"";
						break;
					case "yewu":
						data.head = "UPDATE BAS_BUSSOBJ SET";
						data.where = " WHERE DOCID=\"" + $("yewuid").value +"\"";
						break;
					case "miao":
						data.head = "UPDATE BAS_PRVOBJ SET";
						data.where = " WHERE OID=\"" + $("OID") +"\"";
					default:
						break;	
				}			
				data.type = "update";	
				data.tags = [];
				data.tags[0] = that;
				data.change = data.changeName + "=\"" + data.changeVal + "\"";
				observer.readyPublish.push({
					type : tempType,
					data : data	
				});
				break;
			default:
				break;
		}
	}
	observer.insert = function(typea, num, change) {
		var data = {}, tempType;
		data.type = "insert";
		if(typea == "flw") {
			tempType = "step" + "_" + num;
			data.head = "INSERT INTO BAS_WMFSTEPRLT (BEGDA,ENDDA,RLTST,RLLTP,RLTGP,COHRID,STPCHID,DYRLT,RLTCOL,OPCON,DLFLG,ASNM,FLWID,STPID) VALUES";
			data.change = change;	
		}
		else {
			tempType = "quan" + "_" + num;	
			data.head = "INSERT INTO BAS_PRVOBJSLV (BEGDA,ENDDA,OHRID,PRVTYPE,GUPNUM,HDSQLCON,COMMENT,DLFLG,ASNM,OID,HDOHRID,SQNM) VALUES";
			data.change = change;
		}	
		data.tags = []
		observer.readyPublish.push({
			type : tempType,
			data : data	
		});
	}
	//用于检查删除行时的处理
	observer.checkDel = function(tag, row) {
		var data = {};
		for(var i = 0, reader; reader = observer.readyPublish[i++];) {
			if("step_"+row == reader.type) {
				if("insert" == reader.data.type) {
					observer.readyPublish.splice(i-1, 1);//如果是新增加的行
					if(0 == observer.readyPublish.length) {
						dba.saveBut.style.display = "none";		
					}
				}
				else {
					reader.data.where += ',DLFLG="0"';	
				}
				return false;//如果满足这两种情况就不需要继续了。
			}	
		}
		//执行到这来说明前面的都不满足，给readerPublish新X如一个数据。	
		data.type = "update";
		data.change = 'DLFLG="0"';
		data.head = "UPDATE BAS_WMFSTEPRLT SET";
		data.tags = [];
		data.where = "STPCHID=\"" + tag.cells[6].getElementsByTagName("input")[0].value + "\",OPCON=\"" + tag.cells[6].getElementsByTagName("input")[0].value + "\"";
		observer.readyPublish.push({
			type : tempType,
			data : data	
		});
		dba.saveBut.style.display = "block";	
	}
	/**流程切换提示**/
	function Tip() {
		this.moreThanTwenty	 = false;
	}
	//修改提示框位置。
	Tip.prototype ={
		start : function(event) {
			var event = event || window.event;
			var sKeyCode = event.keyCode;
			var aShangXia = new Array(37,38,39,40);
			var isDerection, tr, td;
			var needToTip = false;
			var sId = 0;//用于给每个名字加一个id的顺序
			var aTempName, tag, sVal, sHtml, mesTag, selectedTag, didTag, widths;
			var postion = new Array();
			var searchPosition = new Array();
			var whichType;//用户输入的类型，是数字呢还是中文。
			sVal = this.inputTag.value;
			//以enter作为用户输入结束标志
			if(13!=sKeyCode) {
				for(var i in aShangXia) {
					if(sKeyCode == aShangXia[i]) {
						isDerection = false;	
						break;
					}	
					else {
						isDerection = true;	
					}
				}
				if(isDerection) {
					sHtml = '';
					if(""==sVal) {
						this.mesTag.className= "change-flw-mes show-block";
						this.mesTag.innerHTML = sHtml;
						return false;	
					}
					else {				
						sHtml = '<table width="270px" cellspacing="0" cellpadding="0" border="0" id="showTable">';
						if(this.checkVal(sVal)) {
							for(var i in this.data)
							{
								sVal = sVal.toUpperCase();
								if(0<=this.data[i].id.indexOf(sVal)) {
									if(20 > sId) {
										sHtml = sHtml + '<tr><td class="mes-td-normal" id="p_'+sId+'" readonly="readonly">'+this.data[i].id+'_'+this.data[i].name+'</td></tr>';
									}
									else {
										needToTip = true;
										break;	
									}
									sId = sId + 1;
								}
							}	
						}
						else {
							for(var i in this.data)
							{	
								if(0<=this.data[i].name.indexOf(sVal)) {
									if(20 > sId) {
										sHtml = sHtml + '<tr><td class="mes-td-normal"  id="p_'+sId+'" readonly="readonly">'+this.data[i].id+'_'+this.data[i].name+'</td></tr>';
									}
									else {
										needToTip = true;
										break;	
									}
									sId = sId + 1;
								}
							}
						}
						sHtml = sHtml + '</table>';
						if(0!=sId) {		
							this.mesTag.className= "change-flw-mes show-block";
							this.mesTag.innerHTML = sHtml;
							sHtml = '';	
							this.moreThanTwenty = false;
							if(needToTip) { 
								tr = $("showTable").insertRow(0);
								td = tr.insertCell(0);
								td.id = "firstTip";
								td.innerHTML = sVal + "查询的结果较多，这里只显示前20条";
								this.moreThanTwenty	 = true;
							}
							sId = 0;
							needToTip = false;
						}
						else {
							this.mesTag.innerHTML = '没有结果';	
						}
					}
				}
				else
				{
					if(38==sKeyCode||40==sKeyCode) {
						dance(sKeyCode,sVal,this.inputTag);
					}		
				}	
			}
			else {
				if(''!=this.inputTag.value) {
					this.mesTag.innerHTML = '';
					this.mesTag.className = "change-flw-mes hide"
				}
				else {
					return false;	
				}	
			}
		},
		changePos: function(){
			var position = _getElePos(this.inputTag);//输入框坐标获取
			var text = "left:"+position[0]+"top:"+position[1];
			//显示div坐标调整
			this.mesTag = document.getElementById("showMessage");
			this.mesTag.setAttribute("style", text);
			function _getElePos(tag) {
				var ua = navigator.userAgent.toLowerCase();
				var isOpera = (ua.indexOf('opera') != -1);
				var isIE = (ua.indexOf('msie') != -1 && !isOpera); // not opera spoof 
				if (tag.parentNode === null || tag.style.display == 'none') {
					return false;
				}
				var parent = null;
				var pos = [];
				var box;
				if (tag.getBoundingClientRect)  
				{
					box = tag.getBoundingClientRect();
					var scrollTop = Math.max(document.documentElement.scrollTop, document.body.scrollTop);
					var scrollLeft = Math.max(document.documentElement.scrollLeft, document.body.scrollLeft);
					pos[0] = box.left + scrollLeft + "px;";
					pos[1] = box.bottom +scrollTop + "px;";
					return pos;
				}
			}
		 },
		 checkVal:function(sVal){
			var patrn = new RegExp("[A-Za-z0-9]");
			if(patrn.exec(sVal)) {
				return true;
			}
			else {
				return false;	
			}
		},
		clickToChoice: function(sqnm) {
			var choicedTag;
			choicedTag = document.getElementById("p_"+sqnm);
			this.inputTag.value = choicedTag.innerHTML;
			this.mesTag.className= "change-flw-mes hide";
		}
	}
	//实例化Tip;
	var startTip = new Tip();
	startTip.inputTag = $("change-flw");
	startTip.content = $("content");
	//切换步骤相应用户操作弹出信息。
	function dance(sKeyCode,sVal,tag) {
		var danceTag = $_class("normal", "td");//这个是正常的行
		var danceingTag = $_class("selected", "td");//这个是前一个被选中的行
		var selectedTag, lastTag, showTag, currentNum, initial;
		var rowNums, selectedNum = 0;
		var danceLen = danceTag.length;
		if(0 != danceingTag.length) {
			showTag = document.getElementById("showTable");
			
			rowNums = showTag.rows.length ;
			if(21 == rowNums) {
				rowNums = 20;	
			}
			currentNum = danceingTag[0].id.split("_")[1] * 1;
			switch(sKeyCode) {
				case 40:
					if(rowNums == (currentNum + 1)) {
						selectedNum = 0;	
					}		
					else {
						selectedNum = currentNum + 1;
					}
					break;
				case 38:
					if(0 == currentNum ) {
						selectedNum = rowNums - 1;	
					}		
					else {
						selectedNum = currentNum - 1;
					}
					break;
			}
		}
		else {
			switch(sKeyCode) {
				case 40:
					currentNum = danceTag.length - 1;
					selectedNum = 0;
					break;
				case 38:
					currentNum = 0;
					selectedNum = danceTag.length - 1;	
					break;
			}	
		}
		lastTag	= document.getElementById("p_"+currentNum);	
		lastTag.className = "mes-td-normal";
		selectedTag = document.getElementById("p_"+selectedNum);	
		selectedTag.className = "mes-td-selected";
		tag.value = selectedTag.innerHTML;			
	}
})(window)
	return goFlow;
})